summaryrefslogtreecommitdiff
path: root/source4/libcli
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-09-11 23:09:26 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:58:39 -0500
commitc0bea2aeb36d4a6b7ed8240d3ed479b2c5c34a16 (patch)
tree5f55d18648ea95db2430aa8e3982997f151a61dd /source4/libcli
parenta06b88863d165d20123ee19f9313249b870ed2be (diff)
downloadsamba-c0bea2aeb36d4a6b7ed8240d3ed479b2c5c34a16.tar.gz
samba-c0bea2aeb36d4a6b7ed8240d3ed479b2c5c34a16.tar.bz2
samba-c0bea2aeb36d4a6b7ed8240d3ed479b2c5c34a16.zip
r2286: Fixes towards krb5 logins into Samba's CIFS server.
These fixes aim particularly at allowing PAC-less logins, as I don't yet generate a PAC in the lorikeet-heimdal KDC. This is for the benifit of a Kerbeors-enabled domain join, which seems to be progressing quite well! Andrew Bartlett (This used to be commit f5a381094dd5bcbd795a134bc4b8b89901b5e3eb)
Diffstat (limited to 'source4/libcli')
-rw-r--r--source4/libcli/auth/clikrb5.c15
-rw-r--r--source4/libcli/auth/gensec_krb5.c164
-rw-r--r--source4/libcli/auth/kerberos.h4
-rw-r--r--source4/libcli/auth/kerberos_verify.c19
4 files changed, 113 insertions, 89 deletions
diff --git a/source4/libcli/auth/clikrb5.c b/source4/libcli/auth/clikrb5.c
index f6f8520b3c..78492d2352 100644
--- a/source4/libcli/auth/clikrb5.c
+++ b/source4/libcli/auth/clikrb5.c
@@ -150,18 +150,23 @@
}
#endif
- void get_auth_data_from_tkt(TALLOC_CTX *mem_ctx,
- DATA_BLOB *auth_data, krb5_ticket *tkt)
+ DATA_BLOB get_auth_data_from_tkt(TALLOC_CTX *mem_ctx,
+ krb5_ticket *tkt)
{
+ DATA_BLOB auth_data = data_blob(NULL, 0);
#if defined(HAVE_KRB5_TKT_ENC_PART2)
- if (tkt && tkt->enc_part2)
- *auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents,
+ if (tkt && tkt->enc_part2
+ && tkt->enc_part2->authorization_data
+ && tkt->enc_part2->authorization_data[0]
+ && tkt->enc_part2->authorization_data[0]->length)
+ auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents,
tkt->enc_part2->authorization_data[0]->length);
#else
if (tkt && tkt->ticket.authorization_data && tkt->ticket.authorization_data->len)
- *auth_data = data_blob(tkt->ticket.authorization_data->val->ad_data.data,
+ auth_data = data_blob(tkt->ticket.authorization_data->val->ad_data.data,
tkt->ticket.authorization_data->val->ad_data.length);
#endif
+ return auth_data;
}
krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt)
diff --git a/source4/libcli/auth/gensec_krb5.c b/source4/libcli/auth/gensec_krb5.c
index 569fd81206..4a97d51c40 100644
--- a/source4/libcli/auth/gensec_krb5.c
+++ b/source4/libcli/auth/gensec_krb5.c
@@ -38,13 +38,14 @@ enum GENSEC_KRB5_STATE {
struct gensec_krb5_state {
TALLOC_CTX *mem_ctx;
DATA_BLOB session_key;
- struct PAC_LOGON_INFO logon_info;
+ struct PAC_LOGON_INFO *logon_info;
enum GENSEC_KRB5_STATE state_position;
krb5_context krb5_context;
krb5_auth_context krb5_auth_context;
krb5_ccache krb5_ccache;
krb5_data ticket;
krb5_keyblock krb5_keyblock;
+ char *peer_principal;
};
#ifdef KRB5_DO_VERIFY_PAC
@@ -56,6 +57,7 @@ static NTSTATUS gensec_krb5_pac_checksum(DATA_BLOB pac_data,
krb5_error_code ret;
krb5_crypto crypto;
Checksum cksum;
+ int i;
cksum.cksumtype = (CKSUMTYPE)sig->type;
cksum.checksum.length = sizeof(sig->signature);
@@ -70,21 +72,19 @@ static NTSTATUS gensec_krb5_pac_checksum(DATA_BLOB pac_data,
DEBUG(0,("krb5_crypto_init() failed\n"));
return NT_STATUS_FOOBAR;
}
-{
-int i;
-for (i=0; i < 40; i++) {
- keyusage = i;
- ret = krb5_verify_checksum(gensec_krb5_state->krb5_context,
- crypto,
- keyusage,
- pac_data.data,
- pac_data.length,
- &cksum);
- if (!ret) {
- DEBUG(0,("PAC Verified: keyusage: %d\n", keyusage));
- break;
+ for (i=0; i < 40; i++) {
+ keyusage = i;
+ ret = krb5_verify_checksum(gensec_krb5_state->krb5_context,
+ crypto,
+ keyusage,
+ pac_data.data,
+ pac_data.length,
+ &cksum);
+ if (!ret) {
+ DEBUG(0,("PAC Verified: keyusage: %d\n", keyusage));
+ break;
+ }
}
-}}
krb5_crypto_destroy(gensec_krb5_state->krb5_context, crypto);
if (ret) {
@@ -99,7 +99,7 @@ for (i=0; i < 40; i++) {
#endif
static NTSTATUS gensec_krb5_decode_pac(TALLOC_CTX *mem_ctx,
- struct PAC_LOGON_INFO *logon_info_out,
+ struct PAC_LOGON_INFO **logon_info_out,
DATA_BLOB blob,
struct gensec_krb5_state *gensec_krb5_state)
{
@@ -220,7 +220,7 @@ static NTSTATUS gensec_krb5_decode_pac(TALLOC_CTX *mem_ctx,
}
#endif
DEBUG(0,("account_name: %s [%s]\n",logon_info->account_name.string, logon_info->full_name.string));
- *logon_info_out = *logon_info;
+ *logon_info_out = logon_info;
return status;
}
@@ -542,16 +542,22 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security, TALL
return nt_status;
}
- /* decode and verify the pac */
- nt_status = gensec_krb5_decode_pac(gensec_krb5_state->mem_ctx, &gensec_krb5_state->logon_info, pac,
- gensec_krb5_state);
+ if (pac.data) {
+ /* decode and verify the pac */
+ nt_status = gensec_krb5_decode_pac(gensec_krb5_state->mem_ctx, &gensec_krb5_state->logon_info, pac,
+ gensec_krb5_state);
+ } else {
+ /* NULL PAC, we might need to figure this information out the hard way */
+ gensec_krb5_state->logon_info = NULL;
+ }
if (NT_STATUS_IS_OK(nt_status)) {
gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
/* wrap that up in a nice GSS-API wrapping */
*out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REP);
+
+ gensec_krb5_state->peer_principal = talloc_steal(gensec_krb5_state->mem_ctx, principal);
}
- SAFE_FREE(principal);
return nt_status;
}
case GENSEC_KRB5_DONE:
@@ -597,88 +603,88 @@ static NTSTATUS gensec_krb5_session_key(struct gensec_security *gensec_security,
return NT_STATUS_NO_USER_SESSION_KEY;
}
}
-/*
-struct gensec_krb5_state {
- TALLOC_CTX *mem_ctx;
- DATA_BLOB session_key;
- struct PAC_LOGON_INFO logon_info;
- enum GENSEC_KRB5_STATE state_position;
- krb5_context krb5_context;
- krb5_auth_context krb5_auth_context;
- krb5_ccache krb5_ccache;
- krb5_data ticket;
- krb5_keyblock krb5_keyblock;
-};
-struct auth_session_info
-{
- TALLOC_CTX *mem_ctx;
- int refcount;
-
- NT_USER_TOKEN *nt_user_token;
-
- struct auth_serversupplied_info *server_info;
-
- DATA_BLOB session_key;
-
- const char *workstation;
-};
-*/
static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security,
struct auth_session_info **session_info_out)
{
+ NTSTATUS nt_status;
struct gensec_krb5_state *gensec_krb5_state = gensec_security->private_data;
TALLOC_CTX *mem_ctx;
+ struct auth_serversupplied_info *server_info = NULL;
struct auth_session_info *session_info = NULL;
- struct PAC_LOGON_INFO *logon_info = &gensec_krb5_state->logon_info;
+ struct PAC_LOGON_INFO *logon_info = gensec_krb5_state->logon_info;
struct nt_user_token *ptoken;
struct dom_sid *sid;
+ char *p;
+ char *principal;
*session_info_out = NULL;
- mem_ctx = talloc_init("krb5: session_info");
-
- session_info = talloc_p(mem_ctx, struct auth_session_info);
- if (!session_info) {
- return NT_STATUS_NO_MEMORY;
- }
-
- session_info->mem_ctx = mem_ctx;
- session_info->refcount = 1;
- session_info->server_info = NULL;
-
- ptoken = talloc_p(session_info->mem_ctx, struct nt_user_token);
- if (!ptoken) {
- return NT_STATUS_NO_MEMORY;
+ nt_status = make_server_info(&server_info, gensec_krb5_state->peer_principal);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
}
- ptoken->num_sids = 0;
+ server_info->guest = False;
- ptoken->user_sids = talloc_array_p(mem_ctx, struct dom_sid*, logon_info->groups_count + 2);
- if (!ptoken->user_sids) {
+ principal = talloc_strdup(server_info->mem_ctx, gensec_krb5_state->peer_principal);
+ p = strchr(principal, '@');
+ if (p) {
+ *p = '\0';
+ }
+ server_info->account_name = principal;
+ server_info->domain = talloc_strdup(server_info->mem_ctx, p++);
+ if (!server_info->domain) {
+ free_server_info(&server_info);
return NT_STATUS_NO_MEMORY;
}
+ nt_status = make_session_info(server_info, &session_info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ free_server_info(&server_info);
+ return nt_status;
+ }
- sid = dom_sid_dup(session_info->mem_ctx, logon_info->dom_sid);
- ptoken->user_sids[0] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->user_rid);
- ptoken->num_sids++;
- sid = dom_sid_dup(session_info->mem_ctx, logon_info->dom_sid);
- ptoken->user_sids[1] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->group_rid);
- ptoken->num_sids++;
+ /* IF we have the PAC - otherwise (TODO) we need to get this
+ * data from elsewere - local ldb, or lookup of some
+ * kind... */
- for (;ptoken->num_sids < logon_info->groups_count; ptoken->num_sids++) {
+ if (logon_info) {
+ ptoken = talloc_p(session_info->mem_ctx, struct nt_user_token);
+ if (!ptoken) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ptoken->num_sids = 0;
+
+ ptoken->user_sids = talloc_array_p(mem_ctx, struct dom_sid*, logon_info->groups_count + 2);
+ if (!ptoken->user_sids) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+
+ sid = dom_sid_dup(session_info->mem_ctx, logon_info->dom_sid);
+ ptoken->user_sids[0] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->user_rid);
+ ptoken->num_sids++;
sid = dom_sid_dup(session_info->mem_ctx, logon_info->dom_sid);
- ptoken->user_sids[ptoken->num_sids] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->groups[ptoken->num_sids - 2].rid);
+ ptoken->user_sids[1] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->group_rid);
+ ptoken->num_sids++;
+
+ for (;ptoken->num_sids < logon_info->groups_count; ptoken->num_sids++) {
+ sid = dom_sid_dup(session_info->mem_ctx, logon_info->dom_sid);
+ ptoken->user_sids[ptoken->num_sids] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->groups[ptoken->num_sids - 2].rid);
+ }
+
+ debug_nt_user_token(DBGC_AUTH, 0, ptoken);
+
+ session_info->nt_user_token = ptoken;
+ } else {
+ session_info->nt_user_token = NULL;
}
-
- debug_nt_user_token(DBGC_AUTH, 0, ptoken);
-
- session_info->nt_user_token = ptoken;
session_info->session_key = data_blob_talloc(session_info->mem_ctx,
- gensec_krb5_state->session_key.data,
- gensec_krb5_state->session_key.length);
+ gensec_krb5_state->session_key.data,
+ gensec_krb5_state->session_key.length);
session_info->workstation = NULL;
diff --git a/source4/libcli/auth/kerberos.h b/source4/libcli/auth/kerberos.h
index e35079a4ee..9d6a5e81ae 100644
--- a/source4/libcli/auth/kerberos.h
+++ b/source4/libcli/auth/kerberos.h
@@ -65,8 +65,8 @@ krb5_error_code ads_krb5_mk_req(krb5_context context,
const char *principal,
krb5_ccache ccache,
krb5_data *outbuf);
-void get_auth_data_from_tkt(TALLOC_CTX *mem_ctx,
- DATA_BLOB *auth_data, krb5_ticket *tkt);
+DATA_BLOB get_auth_data_from_tkt(TALLOC_CTX *mem_ctx,
+ krb5_ticket *tkt);
NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
krb5_context context,
krb5_auth_context auth_context,
diff --git a/source4/libcli/auth/kerberos_verify.c b/source4/libcli/auth/kerberos_verify.c
index 88bf391cfa..843189c884 100644
--- a/source4/libcli/auth/kerberos_verify.c
+++ b/source4/libcli/auth/kerberos_verify.c
@@ -32,6 +32,9 @@ static DATA_BLOB unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data)
DATA_BLOB pac_contents = data_blob(NULL, 0);
ASN1_DATA data;
int data_type;
+ if (!auth_data->length) {
+ return data_blob(NULL, 0);
+ }
asn1_load(&data, *auth_data);
asn1_start_tag(&data, ASN1_SEQUENCE(0));
@@ -95,7 +98,7 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
goto out;
}
/* Look for a CIFS ticket */
- if (!StrnCaseCmp(princ_name, "cifs/", 5)) {
+ if (!StrnCaseCmp(princ_name, "cifs/", 5) || (!StrnCaseCmp(princ_name, "host/", 5))) {
#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK
krb5_auth_con_setuseruserkey(context, auth_context, &kt_entry.keyblock);
#else
@@ -254,6 +257,8 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
char *myname;
BOOL auth_ok = False;
+ char *malloc_principal;
+
ZERO_STRUCT(packet);
ZERO_STRUCTP(auth_data);
ZERO_STRUCTP(ap_rep);
@@ -329,7 +334,7 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
file_save("/tmp/ticket.dat", ticket->data, ticket->length);
#endif
- get_auth_data_from_tkt(mem_ctx, auth_data, tkt);
+ *auth_data = get_auth_data_from_tkt(mem_ctx, tkt);
*auth_data = unwrap_pac(mem_ctx, auth_data);
@@ -342,13 +347,21 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
#endif
if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt),
- principal))) {
+ &malloc_principal))) {
DEBUG(3,("ads_verify_ticket: krb5_unparse_name failed (%s)\n",
error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
}
+ *principal = talloc_strdup(mem_ctx, malloc_principal);
+ SAFE_FREE(malloc_principal);
+ if (!principal) {
+ DEBUG(3,("ads_verify_ticket: talloc_strdup() failed\n"));
+ sret = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+
sret = NT_STATUS_OK;
out: