summaryrefslogtreecommitdiff
path: root/source3/libsmb/clikrb5.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2001-10-11 13:13:06 +0000
committerAndrew Tridgell <tridge@samba.org>2001-10-11 13:13:06 +0000
commit7cd9c611e2a1e0028081863a3678c47bc8af7b55 (patch)
tree2ce652229e5647535c8eaedf1654cfc86636a2cb /source3/libsmb/clikrb5.c
parent49307c26789b3061780d160f4c6fa4863853eddd (diff)
downloadsamba-7cd9c611e2a1e0028081863a3678c47bc8af7b55.tar.gz
samba-7cd9c611e2a1e0028081863a3678c47bc8af7b55.tar.bz2
samba-7cd9c611e2a1e0028081863a3678c47bc8af7b55.zip
added a ASN.1 parser, so now I can properly parse the negTokenInit
packet which means I can extract the service and realm, so we should now work with realms other than the local realm. it also means we now check the list of OIDs given by the server just in case it says that it doesn't support kerberos. In that case we should fall back to NTLMSSP but that isn't written yet. (This used to be commit 395cfeea94febb5280ea57027e8a8a3c7c3f9291)
Diffstat (limited to 'source3/libsmb/clikrb5.c')
-rw-r--r--source3/libsmb/clikrb5.c179
1 files changed, 120 insertions, 59 deletions
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index 0e049c14a1..fb442f7f09 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -27,6 +27,8 @@
#define OID_SPNEGO "1 3 6 1 5 5 2"
#define OID_KERBEROS5 "1 2 840 113554 1 2 2"
+#define CHECK_CALL(x) if (! x) goto failed
+
/*
we can't use krb5_mk_req because w2k wants the service to be in a particular format
*/
@@ -34,60 +36,62 @@ static krb5_error_code krb5_mk_req2(krb5_context context,
krb5_auth_context *auth_context,
const krb5_flags ap_req_options,
const char *service,
- krb5_data *in_data,
+ const char *realm,
krb5_ccache ccache,
krb5_data *outbuf)
{
- krb5_error_code retval;
- krb5_principal server;
- krb5_creds * credsp;
- krb5_creds creds;
- char *realm;
-
- /* we should really get the realm from the negTargInit packet,
- but this will do until I've done the asn1 decoder for that */
- if ((retval = krb5_get_default_realm(context, &realm))) {
- return retval;
- }
-
- retval = krb5_build_principal(context, &server, strlen(realm),
- realm, service, NULL);
- if (retval)
- return retval;
-
- /* obtain ticket & session key */
- memset((char *)&creds, 0, sizeof(creds));
- if ((retval = krb5_copy_principal(context, server, &creds.server)))
- goto cleanup_princ;
-
- if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
- goto cleanup_creds;
-
- if ((retval = krb5_get_credentials(context, 0,
- ccache, &creds, &credsp)))
- goto cleanup_creds;
-
- retval = krb5_mk_req_extended(context, auth_context, ap_req_options,
- in_data, credsp, outbuf);
+ krb5_error_code retval;
+ krb5_principal server;
+ krb5_creds * credsp;
+ krb5_creds creds;
+ krb5_data in_data;
+
+ retval = krb5_build_principal(context, &server, strlen(realm),
+ realm, service, NULL);
+ if (retval) {
+ DEBUG(1,("Failed to build principle for %s@%s\n", service, realm));
+ return retval;
+ }
+
+ /* obtain ticket & session key */
+ memset((char *)&creds, 0, sizeof(creds));
+ if ((retval = krb5_copy_principal(context, server, &creds.server)))
+ goto cleanup_princ;
+
+ if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
+ goto cleanup_creds;
+
+ if ((retval = krb5_get_credentials(context, 0,
+ ccache, &creds, &credsp))) {
+ DEBUG(1,("krb5_get_credentials failed (%d)\n", retval));
+ goto cleanup_creds;
+ }
- krb5_free_creds(context, credsp);
+ in_data.length = 0;
+ retval = krb5_mk_req_extended(context, auth_context, ap_req_options,
+ &in_data, credsp, outbuf);
+ if (retval) {
+ DEBUG(1,("krb5_mk_req_extended failed (%d)\n", retval));
+ }
+
+ krb5_free_creds(context, credsp);
cleanup_creds:
- krb5_free_cred_contents(context, &creds);
+ krb5_free_cred_contents(context, &creds);
cleanup_princ:
- krb5_free_principal(context, server);
+ krb5_free_principal(context, server);
- return retval;
+ return retval;
}
/*
get a kerberos5 ticket for the given service
*/
-static DATA_BLOB krb5_get_ticket(char *service)
+static DATA_BLOB krb5_get_ticket(char *service, char *realm)
{
krb5_error_code retval;
- krb5_data packet, inbuf;
+ krb5_data packet;
krb5_ccache ccdef;
krb5_context context;
krb5_auth_context auth_context = NULL;
@@ -99,8 +103,6 @@ static DATA_BLOB krb5_get_ticket(char *service)
goto failed;
}
- inbuf.length = 0;
-
if ((retval = krb5_cc_default(context, &ccdef))) {
DEBUG(1,("krb5_cc_default failed\n"));
goto failed;
@@ -109,8 +111,8 @@ static DATA_BLOB krb5_get_ticket(char *service)
if ((retval = krb5_mk_req2(context,
&auth_context,
AP_OPTS_MUTUAL_REQUIRED,
- service,
- &inbuf, ccdef, &packet))) {
+ service, realm,
+ ccdef, &packet))) {
DEBUG(1,("krb5_mk_req2 failed\n"));
goto failed;
}
@@ -139,16 +141,16 @@ ASN1_DATA spnego_gen_negTokenInit(uint8 guid[16],
memset(&data, 0, sizeof(data));
- asn1_write(&data, guid, 16);
- asn1_push_tag(&data,ASN1_APPLICATION(0));
- asn1_write_OID(&data,OID_SPNEGO);
- asn1_push_tag(&data,ASN1_CONTEXT(0));
- asn1_push_tag(&data,ASN1_SEQUENCE(0));
+ CHECK_CALL(asn1_write(&data, guid, 16));
+ CHECK_CALL(asn1_push_tag(&data,ASN1_APPLICATION(0)));
+ CHECK_CALL(asn1_write_OID(&data,OID_SPNEGO));
+ CHECK_CALL(asn1_push_tag(&data,ASN1_CONTEXT(0)));
+ CHECK_CALL(asn1_push_tag(&data,ASN1_SEQUENCE(0)));
- asn1_push_tag(&data,ASN1_CONTEXT(0));
- asn1_push_tag(&data,ASN1_SEQUENCE(0));
+ CHECK_CALL(asn1_push_tag(&data,ASN1_CONTEXT(0)));
+ CHECK_CALL(asn1_push_tag(&data,ASN1_SEQUENCE(0)));
for (i=0; OIDs[i]; i++) {
- asn1_write_OID(&data,OIDs[i]);
+ CHECK_CALL(asn1_write_OID(&data,OIDs[i]));
}
asn1_pop_tag(&data);
asn1_pop_tag(&data);
@@ -167,6 +169,62 @@ ASN1_DATA spnego_gen_negTokenInit(uint8 guid[16],
asn1_pop_tag(&data);
return data;
+
+failed:
+ DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data.ofs));
+ asn1_free(&data);
+ return data;
+}
+
+
+/*
+ parse a negTokenInit packet giving a GUID, a list of supported
+ OIDs (the mechanisms) and a principle name string
+*/
+BOOL spnego_parse_negTokenInit(DATA_BLOB blob,
+ uint8 guid[16],
+ char *OIDs[ASN1_MAX_OIDS],
+ char **principle)
+{
+ int i;
+ BOOL ret;
+ ASN1_DATA data;
+
+ asn1_load(&data, blob);
+
+ asn1_read(&data, guid, 16);
+ asn1_start_tag(&data,ASN1_APPLICATION(0));
+ asn1_check_OID(&data,OID_SPNEGO);
+ asn1_start_tag(&data,ASN1_CONTEXT(0));
+ asn1_start_tag(&data,ASN1_SEQUENCE(0));
+
+ asn1_start_tag(&data,ASN1_CONTEXT(0));
+ asn1_start_tag(&data,ASN1_SEQUENCE(0));
+ for (i=0; asn1_tag_remaining(&data) > 0 && i < ASN1_MAX_OIDS; i++) {
+ char *oid = NULL;
+ asn1_read_OID(&data,&oid);
+ OIDs[i] = oid;
+ }
+ OIDs[i] = NULL;
+ asn1_end_tag(&data);
+ asn1_end_tag(&data);
+
+ asn1_start_tag(&data, ASN1_CONTEXT(3));
+ asn1_start_tag(&data, ASN1_SEQUENCE(0));
+ asn1_start_tag(&data, ASN1_CONTEXT(0));
+ asn1_read_GeneralString(&data,principle);
+ asn1_end_tag(&data);
+ asn1_end_tag(&data);
+ asn1_end_tag(&data);
+
+ asn1_end_tag(&data);
+ asn1_end_tag(&data);
+
+ asn1_end_tag(&data);
+
+ ret = !data.has_error;
+ asn1_free(&data);
+ return ret;
}
@@ -229,25 +287,28 @@ static ASN1_DATA spnego_gen_krb5_wrap(DATA_BLOB ticket)
generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
kerberos session setup
*/
-DATA_BLOB spnego_gen_negTokenTarg(struct cli_state *cli)
+DATA_BLOB spnego_gen_negTokenTarg(struct cli_state *cli, char *principle)
{
char *p;
fstring service;
+ char *realm;
DATA_BLOB tkt, ret;
ASN1_DATA tkt_wrapped, targ;
const char *krb_mechs[] =
{"1 2 840 48018 1 2 2", "1 3 6 1 4 1 311 2 2 10", NULL};
- /* the service name is the WINS name of the server in lowercase with
- a $ on the end */
- fstrcpy(service, cli->desthost);
- p = strchr_m(service, '.');
- if (p) *p = 0;
- fstrcat(service, "$");
- strlower(service);
+ fstrcpy(service, principle);
+ p = strchr_m(service, '@');
+ if (!p) {
+ DEBUG(1,("Malformed principle [%s] in spnego_gen_negTokenTarg\n",
+ principle));
+ return data_blob(NULL, 0);
+ }
+ *p = 0;
+ realm = p+1;
/* get a kerberos ticket for the service */
- tkt = krb5_get_ticket(service);
+ tkt = krb5_get_ticket(service, realm);
/* wrap that up in a nice GSS-API wrapping */
tkt_wrapped = spnego_gen_krb5_wrap(tkt);