diff options
author | Andrew Bartlett <abartlet@samba.org> | 2005-01-13 04:46:53 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:08:48 -0500 |
commit | 025bf43aa001ef30c106a33124148c3085f96122 (patch) | |
tree | 58a8542f2281ae9801df7df4745e88a2dda59dc8 /source4/libnet | |
parent | 17725e5fd1649203fcf97a2ec41deb7fc7038efa (diff) | |
download | samba-025bf43aa001ef30c106a33124148c3085f96122.tar.gz samba-025bf43aa001ef30c106a33124148c3085f96122.tar.bz2 samba-025bf43aa001ef30c106a33124148c3085f96122.zip |
r4721: Changes to libnet_passwd to take advantage of the new easier to call
RPC client libs, and to make the fallback between the various SAMR
levels easier to manage.
I'm starting to enjoy the structure that libnet has actually, and I'm
about to build 'net join' on that basis (and I didn't want to have to
duplicate the password set code).
Andrew Bartlett
(This used to be commit f1dd179a50d2c9c81b90a621459c93b0d60e2609)
Diffstat (limited to 'source4/libnet')
-rw-r--r-- | source4/libnet/libnet_passwd.c | 421 | ||||
-rw-r--r-- | source4/libnet/libnet_passwd.h | 16 |
2 files changed, 239 insertions, 198 deletions
diff --git a/source4/libnet/libnet_passwd.c b/source4/libnet/libnet_passwd.c index 9b0d41f950..c36c478733 100644 --- a/source4/libnet/libnet_passwd.c +++ b/source4/libnet/libnet_passwd.c @@ -287,6 +287,206 @@ NTSTATUS libnet_ChangePassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, return NT_STATUS_INVALID_LEVEL; } +static NTSTATUS libnet_SetPassword_samr_handle_26(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r) +{ + NTSTATUS status; + struct samr_SetUserInfo sui; + union samr_UserInfo u_info; + DATA_BLOB session_key; + DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16); + uint8_t confounder[16]; + struct MD5Context md5; + + /* prepare samr_SetUserInfo level 26 */ + ZERO_STRUCT(u_info); + encode_pw_buffer(u_info.info26.password.data, r->samr_handle.in.newpassword, STR_UNICODE); + u_info.info26.pw_len = strlen(r->samr_handle.in.newpassword); + + status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key); + if (!NT_STATUS_IS_OK(status)) { + r->samr_handle.out.error_string = talloc_asprintf(mem_ctx, + "dcerpc_fetch_session_key failed: %s\n", + nt_errstr(status)); + return status; + } + + generate_random_buffer((uint8_t *)confounder, 16); + + MD5Init(&md5); + MD5Update(&md5, confounder, 16); + MD5Update(&md5, session_key.data, session_key.length); + MD5Final(confounded_session_key.data, &md5); + + arcfour_crypt_blob(u_info.info26.password.data, 516, &confounded_session_key); + memcpy(&u_info.info26.password.data[516], confounder, 16); + + sui.in.user_handle = r->samr_handle.in.user_handle; + sui.in.info = &u_info; + sui.in.level = 26; + + /* 7. try samr_SetUserInfo level 26 to set the password */ + status = dcerpc_samr_SetUserInfo(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui); + /* check result of samr_SetUserInfo level 26 */ + if (!NT_STATUS_IS_OK(status)) { + r->samr_handle.out.error_string + = talloc_asprintf(mem_ctx, + "SetUserInfo level 26 for [%s] failed: %s\n", + r->samr_handle.in.account_name, nt_errstr(status)); + } + return status; +} + +static NTSTATUS libnet_SetPassword_samr_handle_25(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r) +{ + NTSTATUS status; + struct samr_SetUserInfo sui; + union samr_UserInfo u_info; + DATA_BLOB session_key; + DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16); + uint8_t confounder[16]; + struct MD5Context md5; + + /* prepare samr_SetUserInfo level 25 */ + ZERO_STRUCT(u_info); + u_info.info25.info.fields_present = SAMR_FIELD_PASSWORD; + encode_pw_buffer(u_info.info25.password.data, r->samr_handle.in.newpassword, STR_UNICODE); + + status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key); + if (!NT_STATUS_IS_OK(status)) { + r->samr_handle.out.error_string = talloc_asprintf(mem_ctx, + "dcerpc_fetch_session_key failed: %s\n", + nt_errstr(status)); + return status; + } + + generate_random_buffer((uint8_t *)confounder, 16); + + MD5Init(&md5); + MD5Update(&md5, confounder, 16); + MD5Update(&md5, session_key.data, session_key.length); + MD5Final(confounded_session_key.data, &md5); + + arcfour_crypt_blob(u_info.info25.password.data, 516, &confounded_session_key); + memcpy(&u_info.info25.password.data[516], confounder, 16); + + sui.in.user_handle = r->samr_handle.in.user_handle; + sui.in.info = &u_info; + sui.in.level = 25; + + /* 8. try samr_SetUserInfo level 25 to set the password */ + status = dcerpc_samr_SetUserInfo(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui); + if (!NT_STATUS_IS_OK(status)) { + r->samr_handle.out.error_string + = talloc_asprintf(mem_ctx, + "SetUserInfo level 25 for [%s] failed: %s\n", + r->samr_handle.in.account_name, nt_errstr(status)); + } + return status; +} + +static NTSTATUS libnet_SetPassword_samr_handle_24(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r) +{ + NTSTATUS status; + struct samr_SetUserInfo sui; + union samr_UserInfo u_info; + DATA_BLOB session_key; + + /* prepare samr_SetUserInfo level 24 */ + ZERO_STRUCT(u_info); + encode_pw_buffer(u_info.info24.password.data, r->samr_handle.in.newpassword, STR_UNICODE); + /* w2k3 ignores this length */ + u_info.info24.pw_len = strlen_m(r->samr_handle.in.newpassword)*2; + + status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key); + if (!NT_STATUS_IS_OK(status)) { + r->samr_handle.out.error_string = talloc_asprintf(mem_ctx, + "dcerpc_fetch_session_key failed: %s\n", + nt_errstr(status)); + return status; + } + + arcfour_crypt_blob(u_info.info24.password.data, 516, &session_key); + + sui.in.user_handle = r->samr_handle.in.user_handle; + sui.in.info = &u_info; + sui.in.level = 24; + + /* 9. try samr_SetUserInfo level 24 to set the password */ + status = dcerpc_samr_SetUserInfo(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui); + if (!NT_STATUS_IS_OK(status)) { + r->samr_handle.out.error_string + = talloc_asprintf(mem_ctx, + "SetUserInfo level 24 for [%s] failed: %s\n", + r->samr_handle.in.account_name, nt_errstr(status)); + } + return status; +} + +static NTSTATUS libnet_SetPassword_samr_handle_23(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r) +{ + NTSTATUS status; + struct samr_SetUserInfo sui; + union samr_UserInfo u_info; + DATA_BLOB session_key; + + /* prepare samr_SetUserInfo level 23 */ + ZERO_STRUCT(u_info); + u_info.info23.info.fields_present = SAMR_FIELD_PASSWORD; + encode_pw_buffer(u_info.info23.password.data, r->samr_handle.in.newpassword, STR_UNICODE); + + status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key); + if (!NT_STATUS_IS_OK(status)) { + r->samr_handle.out.error_string + = talloc_asprintf(mem_ctx, + "dcerpc_fetch_session_key failed: %s\n", + nt_errstr(status)); + return status; + } + + arcfour_crypt_blob(u_info.info23.password.data, 516, &session_key); + + sui.in.user_handle = r->samr_handle.in.user_handle; + sui.in.info = &u_info; + sui.in.level = 23; + + /* 10. try samr_SetUserInfo level 23 to set the password */ + status = dcerpc_samr_SetUserInfo(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui); + if (!NT_STATUS_IS_OK(status)) { + r->samr_handle.out.error_string + = talloc_asprintf(mem_ctx, + "SetUserInfo level 23 for [%s] failed: %s\n", + r->samr_handle.in.account_name, nt_errstr(status)); + } + return status; +} + +/* + * 1. try samr_SetUserInfo level 26 to set the password + * 2. try samr_SetUserInfo level 25 to set the password + * 3. try samr_SetUserInfo level 24 to set the password + * 4. try samr_SetUserInfo level 23 to set the password +*/ +static NTSTATUS libnet_SetPassword_samr_handle(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r) +{ + NTSTATUS status; + enum libnet_SetPassword_level levels[] = { + LIBNET_SET_PASSWORD_SAMR_HANDLE_26, + LIBNET_SET_PASSWORD_SAMR_HANDLE_25, + LIBNET_SET_PASSWORD_SAMR_HANDLE_24, + LIBNET_SET_PASSWORD_SAMR_HANDLE_23, + }; + int i; + + for (i=0; i < ARRAY_SIZE(levels); i++) { + r->generic.level = levels[i]; + status = libnet_SetPassword(ctx, mem_ctx, r); + if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) { + break; + } + } + + return status; +} /* * set a password with DCERPC/SAMR calls * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) @@ -296,10 +496,7 @@ NTSTATUS libnet_ChangePassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, * 4. do a samr_OpenDomain to get a domain handle * 5. do a samr_LookupNames to get the users rid * 6. do a samr_OpenUser to get a user handle - * 7. try samr_SetUserInfo level 26 to set the password - * 8. try samr_SetUserInfo level 25 to set the password - * 8. try samr_SetUserInfo level 24 to set the password - *10. try samr_SetUserInfo level 23 to set the password + * 7 call libnet_SetPassword_samr_handle to set the password */ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r) { @@ -314,12 +511,7 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * struct samr_LookupNames ln; struct samr_OpenUser ou; struct policy_handle u_handle; - struct samr_SetUserInfo sui; - union samr_UserInfo u_info; - DATA_BLOB session_key; - DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16); - uint8_t confounder[16]; - struct MD5Context md5; + union libnet_SetPassword r2; /* prepare connect to the SAMR pipe of users domain PDC */ c.pdc.level = LIBNET_RPC_CONNECT_PDC; @@ -332,8 +524,8 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * status = libnet_rpc_connect(ctx, mem_ctx, &c); if (!NT_STATUS_IS_OK(status)) { r->samr.out.error_string = talloc_asprintf(mem_ctx, - "Connection to SAMR pipe of PDC of domain '%s' failed: %s\n", - r->samr.in.domain_name, nt_errstr(status)); + "Connection to SAMR pipe of PDC of domain '%s' failed: %s\n", + r->samr.in.domain_name, nt_errstr(status)); return status; } @@ -435,7 +627,7 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * r->samr.in.account_name, nt_errstr(ln.out.result)); status = ln.out.result; goto disconnect; - } +} /* check if we got one RID for the user */ if (ln.out.rids.count != 1) { @@ -471,193 +663,15 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * goto disconnect; } - /* prepare samr_SetUserInfo level 26 */ - ZERO_STRUCT(u_info); - encode_pw_buffer(u_info.info26.password.data, r->samr.in.newpassword, STR_UNICODE); - u_info.info26.pw_len = strlen(r->samr.in.newpassword); - - status = dcerpc_fetch_session_key(c.pdc.out.dcerpc_pipe, &session_key); - if (!NT_STATUS_IS_OK(status)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "dcerpc_fetch_session_key failed: %s\n", - nt_errstr(status)); - goto disconnect; - } - - generate_random_buffer((uint8_t *)confounder, 16); - - MD5Init(&md5); - MD5Update(&md5, confounder, 16); - MD5Update(&md5, session_key.data, session_key.length); - MD5Final(confounded_session_key.data, &md5); - - arcfour_crypt_blob(u_info.info26.password.data, 516, &confounded_session_key); - memcpy(&u_info.info26.password.data[516], confounder, 16); - - sui.in.user_handle = &u_handle; - sui.in.info = &u_info; - sui.in.level = 26; - - /* 7. try samr_SetUserInfo level 26 to set the password */ - status = dcerpc_samr_SetUserInfo(c.pdc.out.dcerpc_pipe, mem_ctx, &sui); - if (!NT_STATUS_IS_OK(status)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "SetUserInfo level 26 for [%s] failed: %s\n", - r->samr.in.account_name, nt_errstr(status)); - goto UserInfo25; - } - - /* check result of samr_SetUserInfo level 26 */ - if (!NT_STATUS_IS_OK(sui.out.result)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "SetUserInfo level 26 for [%s] failed: %s\n", - r->samr.in.account_name, nt_errstr(sui.out.result)); - if (NT_STATUS_EQUAL(sui.out.result, NT_STATUS_WRONG_PASSWORD)) { - status = sui.out.result; - goto disconnect; - } - goto UserInfo25; - } - - goto disconnect; - -UserInfo25: - /* prepare samr_SetUserInfo level 25 */ - ZERO_STRUCT(u_info); - u_info.info25.info.fields_present = SAMR_FIELD_PASSWORD; - encode_pw_buffer(u_info.info25.password.data, r->samr.in.newpassword, STR_UNICODE); - - status = dcerpc_fetch_session_key(c.pdc.out.dcerpc_pipe, &session_key); - if (!NT_STATUS_IS_OK(status)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "dcerpc_fetch_session_key failed: %s\n", - nt_errstr(status)); - goto disconnect; - } - - generate_random_buffer((uint8_t *)confounder, 16); - - MD5Init(&md5); - MD5Update(&md5, confounder, 16); - MD5Update(&md5, session_key.data, session_key.length); - MD5Final(confounded_session_key.data, &md5); - - arcfour_crypt_blob(u_info.info25.password.data, 516, &confounded_session_key); - memcpy(&u_info.info25.password.data[516], confounder, 16); + r2.samr_handle.level = LIBNET_SET_PASSWORD_SAMR_HANDLE; + r2.samr_handle.in.account_name = r->samr.in.account_name; + r2.samr_handle.in.newpassword = r->samr.in.newpassword; + r2.samr_handle.in.user_handle = &u_handle; + r2.samr_handle.in.dcerpc_pipe = c.pdc.out.dcerpc_pipe; - sui.in.user_handle = &u_handle; - sui.in.info = &u_info; - sui.in.level = 25; - - /* 8. try samr_SetUserInfo level 25 to set the password */ - status = dcerpc_samr_SetUserInfo(c.pdc.out.dcerpc_pipe, mem_ctx, &sui); - if (!NT_STATUS_IS_OK(status)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "SetUserInfo level 25 for [%s] failed: %s\n", - r->samr.in.account_name, nt_errstr(status)); - goto UserInfo24; - } - - /* check result of samr_SetUserInfo level 25 */ - if (!NT_STATUS_IS_OK(sui.out.result)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "SetUserInfo level 25 for [%s] failed: %s\n", - r->samr.in.account_name, nt_errstr(sui.out.result)); - if (NT_STATUS_EQUAL(sui.out.result, NT_STATUS_WRONG_PASSWORD)) { - status = sui.out.result; - goto disconnect; - } - goto UserInfo24; - } - - goto disconnect; - -UserInfo24: - /* prepare samr_SetUserInfo level 24 */ - ZERO_STRUCT(u_info); - encode_pw_buffer(u_info.info24.password.data, r->samr.in.newpassword, STR_UNICODE); - /* w2k3 ignores this length */ - u_info.info24.pw_len = strlen_m(r->samr.in.newpassword)*2; - - status = dcerpc_fetch_session_key(c.pdc.out.dcerpc_pipe, &session_key); - if (!NT_STATUS_IS_OK(status)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "dcerpc_fetch_session_key failed: %s\n", - nt_errstr(status)); - goto disconnect; - } - - arcfour_crypt_blob(u_info.info24.password.data, 516, &session_key); - - sui.in.user_handle = &u_handle; - sui.in.info = &u_info; - sui.in.level = 24; - - /* 9. try samr_SetUserInfo level 24 to set the password */ - status = dcerpc_samr_SetUserInfo(c.pdc.out.dcerpc_pipe, mem_ctx, &sui); - if (!NT_STATUS_IS_OK(status)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "SetUserInfo level 24 for [%s] failed: %s\n", - r->samr.in.account_name, nt_errstr(status)); - goto UserInfo23; - } - - /* check result of samr_SetUserInfo level 24 */ - if (!NT_STATUS_IS_OK(sui.out.result)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "SetUserInfo level 24 for [%s] failed: %s\n", - r->samr.in.account_name, nt_errstr(sui.out.result)); - if (NT_STATUS_EQUAL(sui.out.result, NT_STATUS_WRONG_PASSWORD)) { - status = sui.out.result; - goto disconnect; - } - goto UserInfo23; - } - - goto disconnect; - -UserInfo23: - /* prepare samr_SetUserInfo level 23 */ - ZERO_STRUCT(u_info); - u_info.info23.info.fields_present = SAMR_FIELD_PASSWORD; - encode_pw_buffer(u_info.info23.password.data, r->samr.in.newpassword, STR_UNICODE); - - status = dcerpc_fetch_session_key(c.pdc.out.dcerpc_pipe, &session_key); - if (!NT_STATUS_IS_OK(status)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "dcerpc_fetch_session_key failed: %s\n", - nt_errstr(status)); - goto disconnect; - } - - arcfour_crypt_blob(u_info.info23.password.data, 516, &session_key); - - sui.in.user_handle = &u_handle; - sui.in.info = &u_info; - sui.in.level = 23; - - /* 10. try samr_SetUserInfo level 23 to set the password */ - status = dcerpc_samr_SetUserInfo(c.pdc.out.dcerpc_pipe, mem_ctx, &sui); - if (!NT_STATUS_IS_OK(status)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "SetUserInfo level 23 for [%s] failed: %s\n", - r->samr.in.account_name, nt_errstr(status)); - goto disconnect; - } - - /* check result of samr_SetUserInfo level 23 */ - if (!NT_STATUS_IS_OK(sui.out.result)) { - r->samr.out.error_string = talloc_asprintf(mem_ctx, - "SetUserInfo level 23 for [%s] failed: %s\n", - r->samr.in.account_name, nt_errstr(sui.out.result)); - if (NT_STATUS_EQUAL(sui.out.result, NT_STATUS_WRONG_PASSWORD)) { - status = sui.out.result; - goto disconnect; - } - goto disconnect; - } + status = libnet_SetPassword(ctx, mem_ctx, &r2); - goto disconnect; + r->generic.out.error_string = r2.samr_handle.out.error_string; disconnect: /* close connection */ @@ -676,6 +690,7 @@ static NTSTATUS libnet_SetPassword_generic(struct libnet_context *ctx, TALLOC_CT r2.samr.in.domain_name = r->generic.in.domain_name; r2.samr.in.newpassword = r->generic.in.newpassword; + r->generic.out.error_string = "Unknown Error"; status = libnet_SetPassword(ctx, mem_ctx, &r2); r->generic.out.error_string = r2.samr.out.error_string; @@ -690,6 +705,16 @@ NTSTATUS libnet_SetPassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, uni return libnet_SetPassword_generic(ctx, mem_ctx, r); case LIBNET_SET_PASSWORD_SAMR: return libnet_SetPassword_samr(ctx, mem_ctx, r); + case LIBNET_SET_PASSWORD_SAMR_HANDLE: + return libnet_SetPassword_samr_handle(ctx, mem_ctx, r); + case LIBNET_SET_PASSWORD_SAMR_HANDLE_26: + return libnet_SetPassword_samr_handle_26(ctx, mem_ctx, r); + case LIBNET_SET_PASSWORD_SAMR_HANDLE_25: + return libnet_SetPassword_samr_handle_25(ctx, mem_ctx, r); + case LIBNET_SET_PASSWORD_SAMR_HANDLE_24: + return libnet_SetPassword_samr_handle_24(ctx, mem_ctx, r); + case LIBNET_SET_PASSWORD_SAMR_HANDLE_23: + return libnet_SetPassword_samr_handle_23(ctx, mem_ctx, r); case LIBNET_SET_PASSWORD_KRB5: return NT_STATUS_NOT_IMPLEMENTED; case LIBNET_SET_PASSWORD_LDAP: diff --git a/source4/libnet/libnet_passwd.h b/source4/libnet/libnet_passwd.h index f3b0f76e57..d7b284cb74 100644 --- a/source4/libnet/libnet_passwd.h +++ b/source4/libnet/libnet_passwd.h @@ -72,6 +72,11 @@ union libnet_ChangePassword { enum libnet_SetPassword_level { LIBNET_SET_PASSWORD_GENERIC, LIBNET_SET_PASSWORD_SAMR, + LIBNET_SET_PASSWORD_SAMR_HANDLE, + LIBNET_SET_PASSWORD_SAMR_HANDLE_26, + LIBNET_SET_PASSWORD_SAMR_HANDLE_25, + LIBNET_SET_PASSWORD_SAMR_HANDLE_24, + LIBNET_SET_PASSWORD_SAMR_HANDLE_23, LIBNET_SET_PASSWORD_KRB5, LIBNET_SET_PASSWORD_LDAP, LIBNET_SET_PASSWORD_RAP @@ -94,6 +99,17 @@ union libnet_SetPassword { struct { enum libnet_SetPassword_level level; + struct _libnet_SetPassword_samr_handle_in { + const char *account_name; /* for debug only */ + struct policy_handle *user_handle; + struct dcerpc_pipe *dcerpc_pipe; + const char *newpassword; + } in; + struct _libnet_SetPassword_out out; + } samr_handle; + + struct { + enum libnet_SetPassword_level level; struct _libnet_SetPassword_in in; struct _libnet_SetPassword_out out; } samr; |