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
}
}
+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. */
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;
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;
}
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;
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;
}
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"));
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:
********************************************************************/
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"));
********************************************************************/
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"));
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;
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);
* 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);
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);
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",
/* 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;
}
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
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);
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) &&