Merge from 3.0:
authorAndrew Bartlett <abartlet@samba.org>
Sun, 23 Nov 2003 00:22:17 +0000 (00:22 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Sun, 23 Nov 2003 00:22:17 +0000 (00:22 +0000)
Add support for variable-length session keys in our client code.

This means that we now support 'net rpc join' with KRB5 (des based)
logins.  Now, you need to hack 'net' to do that, but the principal is
important...

When we add kerberos to 'net rpc', it should be possible to still do
user management and the like over RPC.

-

Add server-side support for variable-length session keys (as used by
DES based krb5 logins).

Andrew Bartlett

source/libsmb/smbdes.c
source/rpc_client/cli_samr.c
source/rpc_parse/parse_samr.c
source/rpc_server/srv_samr_nt.c
source/utils/net_rpc.c
source/utils/net_rpc_join.c

index cde77f94a36047001c697a9c0e28089b54544ef7..ae946b4a66090cba869c1565a965b1f51e3d722d 100644 (file)
@@ -397,6 +397,46 @@ void SamOEMhash( unsigned char *data, const unsigned char *key, int val)
   }
 }
 
+void SamOEMhashBlob( unsigned char *data, int len, DATA_BLOB *key)
+{
+  unsigned char s_box[256];
+  unsigned char index_i = 0;
+  unsigned char index_j = 0;
+  unsigned char j = 0;
+  int ind;
+
+  for (ind = 0; ind < 256; ind++)
+  {
+    s_box[ind] = (unsigned char)ind;
+  }
+
+  for( ind = 0; ind < 256; ind++)
+  {
+     unsigned char tc;
+
+     j += (s_box[ind] + key->data[ind%key->length]);
+
+     tc = s_box[ind];
+     s_box[ind] = s_box[j];
+     s_box[j] = tc;
+  }
+  for( ind = 0; ind < len; ind++)
+  {
+    unsigned char tc;
+    unsigned char t;
+
+    index_i++;
+    index_j += s_box[index_i];
+
+    tc = s_box[index_i];
+    s_box[index_i] = s_box[index_j];
+    s_box[index_j] = tc;
+
+    t = s_box[index_i] + s_box[index_j];
+    data[ind] = data[ind] ^ s_box[t];
+  }
+}
+
 /* Decode a sam password hash into a password.  The password hash is the
    same method used to store passwords in the NT registry.  The DES key
    used is based on the RID of the user. */
index 9bab816b8147366274aa2197f9030b2cb4124a37..0eebcd0a6f51204f09f28c42c454ce76157ba020 100644 (file)
@@ -1341,7 +1341,7 @@ NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
                                POLICY_HND *user_pol, uint16 switch_value,
-                               DATA_BLOB sess_key, SAM_USERINFO_CTR *ctr)
+                               DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
        SAMR_Q_SET_USERINFO q;
@@ -1353,8 +1353,8 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       if (sess_key.length != 16) {
-               DEBUG(1, ("Cannot handle user session key of length [%u]\n", sess_key.length));
+       if (!sess_key->length) {
+               DEBUG(1, ("No user session key\n"));
                return NT_STATUS_NO_USER_SESSION_KEY;
        }
 
@@ -1398,7 +1398,7 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
                                 POLICY_HND *user_pol, uint16 switch_value,
-                                DATA_BLOB sess_key, SAM_USERINFO_CTR *ctr)
+                                DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
        SAMR_Q_SET_USERINFO2 q;
@@ -1407,8 +1407,8 @@ NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        DEBUG(10,("cli_samr_set_userinfo2\n"));
 
-       if (sess_key.length != 16) {
-               DEBUG(1, ("Cannot handle user session key of length [%u]\n", sess_key.length));
+       if (!sess_key->length) {
+               DEBUG(1, ("No user session key\n"));
                return NT_STATUS_NO_USER_SESSION_KEY;
        }
 
index 19665383627c8f38e6689ece821cc1aa60e576a6..5e3502b24229c673f99615ba6a7e544af6d8015a 100644 (file)
@@ -6302,8 +6302,8 @@ NTSTATUS make_samr_userinfo_ctr_usr21(TALLOC_CTX *ctx, SAM_USERINFO_CTR * ctr,
 inits a SAM_USERINFO_CTR structure.
 ********************************************************************/
 
-void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, DATA_BLOB sess_key,
-                           uint16 switch_value, void *info)
+static void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, DATA_BLOB *sess_key,
+                                  uint16 switch_value, void *info)
 {
        DEBUG(5, ("init_samr_userinfo_ctr\n"));
 
@@ -6312,13 +6312,13 @@ void init_samr_userinfo_ctr(SAM_USERINFO_CTR * ctr, DATA_BLOB sess_key,
 
        switch (switch_value) {
        case 0x18:
-               SamOEMhash(ctr->info.id24->pass, sess_key.data, 516);
-               dump_data(100, (char *)sess_key.data, 16);
+               SamOEMhashBlob(ctr->info.id24->pass, 516, sess_key);
+               dump_data(100, (char *)sess_key->data, sess_key->length);
                dump_data(100, (char *)ctr->info.id24->pass, 516);
                break;
        case 0x17:
-               SamOEMhash(ctr->info.id23->pass, sess_key.data, 516);
-               dump_data(100, (char *)sess_key.data, 16);
+               SamOEMhashBlob(ctr->info.id23->pass, 516, sess_key);
+               dump_data(100, (char *)sess_key->data, sess_key->length);
                dump_data(100, (char *)ctr->info.id23->pass, 516);
                break;
        default:
@@ -6503,7 +6503,7 @@ inits a SAMR_Q_SET_USERINFO structure.
 ********************************************************************/
 
 void init_samr_q_set_userinfo(SAMR_Q_SET_USERINFO * q_u,
-                             POLICY_HND *hnd, DATA_BLOB sess_key,
+                             POLICY_HND *hnd, DATA_BLOB *sess_key,
                              uint16 switch_value, void *info)
 {
        DEBUG(5, ("init_samr_q_set_userinfo\n"));
@@ -6577,7 +6577,7 @@ inits a SAMR_Q_SET_USERINFO2 structure.
 ********************************************************************/
 
 void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
-                              POLICY_HND *hnd, DATA_BLOB sess_key,
+                              POLICY_HND *hnd, DATA_BLOB *sess_key,
                               uint16 switch_value, SAM_USERINFO_CTR * ctr)
 {
        DEBUG(5, ("init_samr_q_set_userinfo2\n"));
@@ -6591,9 +6591,9 @@ void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
 
        switch (switch_value) {
        case 0x12:
-               SamOEMhash(ctr->info.id12->lm_pwd, sess_key.data, 16);
-               SamOEMhash(ctr->info.id12->nt_pwd, sess_key.data, 16);
-               dump_data(100, (char *)sess_key.data, 16);
+               SamOEMhashBlob(ctr->info.id12->lm_pwd, 16, sess_key);
+               SamOEMhashBlob(ctr->info.id12->nt_pwd, 16, sess_key);
+               dump_data(100, (char *)sess_key->data, sess_key->length);
                dump_data(100, (char *)ctr->info.id12->lm_pwd, 16);
                dump_data(100, (char *)ctr->info.id12->nt_pwd, 16);
                break;
index 1debf90d23d3cb822d32fe74f655f6b2d4a0d66d..6cd5da4892f802f29de34cbba75035159ac569a8 100644 (file)
@@ -2953,13 +2953,10 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
                        break;
 
                case 24:
-                       if (p->session_key.length != 16) {
-                               /* we may have no session key at all, 
-                                  and we don't know how to do the SamOEMhash 
-                                  for length != 16 */
+                       if (!p->session_key.length) {
                                return NT_STATUS_NO_USER_SESSION_KEY;
                        }
-                       SamOEMhash(ctr->info.id24->pass, p->session_key.data, 516);
+                       SamOEMhashBlob(ctr->info.id24->pass, 516, &p->session_key);
 
                        dump_data(100, (char *)ctr->info.id24->pass, 516);
 
@@ -2977,10 +2974,10 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
                         * info level and W2K SP2 drops down to level 23... JRA.
                         */
 
-                       if (p->session_key.length != 16) {
+                       if (!p->session_key.length) {
                                return NT_STATUS_NO_USER_SESSION_KEY;
                        }
-                       SamOEMhash(ctr->info.id25->pass, p->session_key.data, 532);
+                       SamOEMhashBlob(ctr->info.id25->pass, 532, &p->session_key);
 
                        dump_data(100, (char *)ctr->info.id25->pass, 532);
 
@@ -2991,10 +2988,10 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
                        return NT_STATUS_INVALID_INFO_CLASS;
 
                case 23:
-                       if (p->session_key.length != 16) {
+                       if (!p->session_key.length) {
                                return NT_STATUS_NO_USER_SESSION_KEY;
                        }
-                       SamOEMhash(ctr->info.id23->pass, p->session_key.data, 516);
+                       SamOEMhashBlob(ctr->info.id23->pass, 516, &p->session_key);
 
                        dump_data(100, (char *)ctr->info.id23->pass, 516);
 
index 298e8ff6690772bf9431bfce80da1c93e791d624..747fc63e23ecebfe8ccd819f8ff78aa467bf62bb 100644 (file)
@@ -1727,7 +1727,7 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli
                ctr.info.id24 = &p24;
 
                result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24,
-                                              cli->user_session_key, &ctr);
+                                              &cli->user_session_key, &ctr);
 
                if (!NT_STATUS_IS_OK(result)) {
                        DEBUG(0,("Could not set trust account password: %s\n",
index 22ed49c74f6b9bd796b229d761824acfe92db123..96943468ad2e05746a2344ff8e233d63671dd106 100644 (file)
@@ -70,7 +70,7 @@ int net_rpc_join_ok(const char *domain)
        /* ensure that schannel uses the right domain */
        fstrcpy(cli->domain, domain);
        if (! NT_STATUS_IS_OK(result = cli_nt_establish_netlogon(cli, channel, stored_md4_trust_password))) {
-               DEBUG(0,("Error in domain join verfication\n"));
+               DEBUG(0,("Error in domain join verfication (fresh connection)\n"));
                goto done;
        }
        
@@ -282,7 +282,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        ctr.info.id24 = &p24;
 
        CHECK_RPC_ERR(cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24, 
-                                           cli->user_session_key, &ctr),
+                                           &cli->user_session_key, &ctr),
                      "error setting trust account password");
 
        /* Why do we have to try to (re-)set the ACB to be the same as what
@@ -304,7 +304,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
           as a normal user with "Add workstation to domain" privilege. */
 
        result = cli_samr_set_userinfo2(cli, mem_ctx, &user_pol, 0x10, 
-                                       cli->user_session_key, &ctr);
+                                       &cli->user_session_key, &ctr);
 
        /* Now check the whole process from top-to-bottom */
        cli_samr_close(cli, mem_ctx, &user_pol);
@@ -322,7 +322,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
                                           md4_trust_password);
 
        if (!NT_STATUS_IS_OK(result)) {
-               DEBUG(0, ("Error domain join verification: %s\n\n",
+               DEBUG(0, ("Error domain join verification (reused connection): %s\n\n",
                          nt_errstr(result)));
 
                if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) &&