W00t! Client smb signing is now working correctly with krb5 and w2k server.
authorJeremy Allison <jra@samba.org>
Fri, 25 Jul 2003 23:15:30 +0000 (23:15 +0000)
committerJeremy Allison <jra@samba.org>
Fri, 25 Jul 2003 23:15:30 +0000 (23:15 +0000)
Server code *should* also work (I'll check shortly). May be the odd memory
leak. Problem was we (a) weren't setting signing on in the client krb5 sessionsetup
code (b) we need to ask for a subkey... (c). The client and server need to
ask for local and remote subkeys respectively.
Thanks to Paul Nelson @ Thursby for some sage advice on this :-).
Jeremy.

source/include/includes.h
source/libads/kerberos_verify.c
source/libads/sasl.c
source/libsmb/cliconnect.c
source/libsmb/clikrb5.c
source/libsmb/clispnego.c
source/libsmb/smb_signing.c

index 77c2b437bddf2bc7f64a49b985d014f7460aa70d..d900d7feb9f230c7b8057f9d6fb122e59bff8de4 100644 (file)
@@ -1296,7 +1296,7 @@ krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt);
 krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters);
 krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes);
 void free_kerberos_etypes(krb5_context context, krb5_enctype *enctypes);
-BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16]);
+BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16], BOOL remote);
 #endif /* HAVE_KRB5 */
 
 /* TRUE and FALSE are part of the C99 standard and gcc, but
index 25b7f9d948b66676ff8dd4c2345e2c68e8ff2782..4098b44c394ebaff12f3b310396b37475ca60621 100644 (file)
@@ -178,7 +178,7 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
        *ap_rep = data_blob(packet.data, packet.length);
        free(packet.data);
 
-       get_krb5_smb_session_key(context, auth_context, session_key);
+       get_krb5_smb_session_key(context, auth_context, session_key, True);
 #ifdef DEBUG_PASSWORD
        DEBUG(10,("SMB session key (from ticket) follows:\n"));
        dump_data(10, session_key, 16);
index 598208b17f8e80c7691e171c2eb3d3389ddc5588..910ff3f4dc6682e1fcdcc619b43ec4796a859e5f 100644 (file)
@@ -124,9 +124,10 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
 {
        DATA_BLOB blob;
        struct berval cred, *scred;
+       unsigned char sk[16];
        int rc;
 
-       blob = spnego_gen_negTokenTarg(principal, ads->auth.time_offset);
+       blob = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, sk);
 
        if (!blob.data) {
                return ADS_ERROR(LDAP_OPERATIONS_ERROR);
index eceeb963093c98e505d924db99d4244face4a31e..8873c1fdc82eaf835c8ef40577682487de8018b5 100644 (file)
@@ -472,6 +472,7 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
 /****************************************************************************
  Use in-memory credentials cache
 ****************************************************************************/
+
 static void use_in_memory_ccache(void) {
        setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
 }
@@ -483,18 +484,23 @@ static void use_in_memory_ccache(void) {
 static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
 {
        DATA_BLOB blob2, negTokenTarg;
-
+       unsigned char session_key_krb5[16];
+       DATA_BLOB null_blob = data_blob(NULL, 0);
+       
        DEBUG(2,("Doing kerberos session setup\n"));
 
        /* generate the encapsulated kerberos5 ticket */
-       negTokenTarg = spnego_gen_negTokenTarg(principal, 0);
+       negTokenTarg = spnego_gen_negTokenTarg(principal, 0, session_key_krb5);
 
-       if (!negTokenTarg.data) return False;
+       if (!negTokenTarg.data)
+               return False;
 
 #if 0
        file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
 #endif
 
+       cli_simple_set_signing(cli, session_key_krb5, null_blob); 
+                       
        blob2 = cli_session_setup_blob(cli, negTokenTarg);
 
        /* we don't need this blob for kerberos */
@@ -551,7 +557,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
                                                  blob_in, &blob_out);
                data_blob_free(&blob_in);
                if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-                       DATA_BLOB null = data_blob(NULL, 0);
+                       DATA_BLOB null_blob = data_blob(NULL, 0);
                        if (turn == 1) {
                                /* and wrap it in a SPNEGO wrapper */
                                msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
@@ -562,7 +568,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
                
                        cli_simple_set_signing(cli, 
                                               ntlmssp_state->session_key.data, 
-                                              null); 
+                                              null_blob); 
                        
                        /* now send that blob on its way */
                        if (!cli_session_setup_blob_send(cli, msg1)) {
index ba8ba11368a5570afa89c9454f35bc2ed98a6aad..beac8cb2c1d3f18f17e99e4e060fbd456258a8a2 100644 (file)
@@ -305,7 +305,7 @@ cleanup_princ:
 /*
   get a kerberos5 ticket for the given service 
 */
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset)
+DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, unsigned char session_key_krb5[16])
 {
        krb5_error_code retval;
        krb5_data packet;
@@ -345,13 +345,15 @@ DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset)
        }
 
        if ((retval = ads_krb5_mk_req(context, 
-                                     &auth_context, 
-                                     0
-                                     principal,
-                                     ccdef, &packet))) {
+                                       &auth_context, 
+                                       AP_OPTS_USE_SUBKEY
+                                       principal,
+                                       ccdef, &packet))) {
                goto failed;
        }
 
+       get_krb5_smb_session_key(context, auth_context, session_key_krb5, False);
+
        ret = data_blob(packet.data, packet.length);
 /* Hmm, heimdal dooesn't have this - what's the correct call? */
 /*     krb5_free_data_contents(context, &packet); */
@@ -365,17 +367,22 @@ failed:
        return data_blob(NULL, 0);
 }
 
- BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16])
+ BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16], BOOL remote)
  {
 #ifdef ENCTYPE_ARCFOUR_HMAC
        krb5_keyblock *skey;
 #endif
        BOOL ret = False;
+       krb5_error_code err;
 
        memset(session_key, 0, 16);
 
 #ifdef ENCTYPE_ARCFOUR_HMAC
-       if (krb5_auth_con_getremotesubkey(context, auth_context, &skey) == 0 && skey != NULL) {
+       if (remote)
+               err = krb5_auth_con_getremotesubkey(context, auth_context, &skey);
+       else
+               err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey);
+       if (err == 0 && skey != NULL) {
                if (KRB5_KEY_TYPE(skey) ==
                    ENCTYPE_ARCFOUR_HMAC
                    && KRB5_KEY_LENGTH(skey) == 16) {
@@ -403,7 +410,7 @@ failed:
 
 #else /* HAVE_KRB5 */
  /* this saves a few linking headaches */
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset)
+DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, unsigned char session_key_krb5[16])
  {
         DEBUG(0,("NO KERBEROS SUPPORT\n"));
         return data_blob(NULL, 0);
index bb48f57915171d6b99f7583d31b54e468b58e1fd..fbf83236795ec2a98db9e5758eae70da4ecf8bf3 100644 (file)
@@ -323,13 +323,13 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
    generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
    kerberos session setup 
 */
-DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset)
+DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset, unsigned char session_key_krb5[16])
 {
        DATA_BLOB tkt, tkt_wrapped, targ;
        const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
 
-       /* get a kerberos ticket for the service */
-       tkt = cli_krb5_get_ticket(principal, time_offset);
+       /* get a kerberos ticket for the service and extract the session key */
+       tkt = cli_krb5_get_ticket(principal, time_offset, session_key_krb5);
 
        /* wrap that up in a nice GSS-API wrapping */
        tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
index 4a98b84826a9517c3e6041ed736eb296d98128a1..977d5e39054e9aa9e45a8cdd9f14a7bd3b2a1702 100644 (file)
@@ -330,6 +330,21 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si)
                
                DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
                dump_data(5, server_sent_mac, 8);
+#if 0 /* JRATEST */
+               {
+                       int i;
+                       reply_seq_number -= 5;
+                       for (i = 0; i < 10; i++, reply_seq_number++) {
+                               simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac);
+                               if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
+                                       DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches.\n",
+                                                       reply_seq_number ));
+                                       break;
+                               }
+                       }
+               }
+#endif /* JRATEST */
+
        }
        return signing_good(inbuf, si, good);
 }