diff options
-rw-r--r-- | source3/lib/netapi/user.c | 175 |
1 files changed, 126 insertions, 49 deletions
diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c index f896dde3aa..faf1a6d65c 100644 --- a/source3/lib/netapi/user.c +++ b/source3/lib/netapi/user.c @@ -27,9 +27,8 @@ /**************************************************************** ****************************************************************/ -static void convert_USER_INFO_1_to_samr_user_info25(struct USER_INFO_1 *info1, - DATA_BLOB *user_session_key, - struct samr_UserInfo25 *info25) +static void convert_USER_INFO_X_to_samr_user_info21(struct USER_INFO_X *infoX, + struct samr_UserInfo21 *info21) { uint32_t fields_present = SAMR_FIELD_ACCT_FLAGS; struct samr_LogonHours zero_logon_hours; @@ -37,41 +36,41 @@ static void convert_USER_INFO_1_to_samr_user_info25(struct USER_INFO_1 *info1, uint32_t acct_flags = 0; NTTIME password_age; - ZERO_STRUCTP(info25); + ZERO_STRUCTP(info21); ZERO_STRUCT(zero_logon_hours); ZERO_STRUCT(zero_parameters); - if (info1->usri1_name) { + if (infoX->usriX_name) { fields_present |= SAMR_FIELD_FULL_NAME; } - if (info1->usri1_password) { + if (infoX->usriX_password) { fields_present |= SAMR_FIELD_PASSWORD; } - if (info1->usri1_flags) { + if (infoX->usriX_flags) { fields_present |= SAMR_FIELD_ACCT_FLAGS; } - if (info1->usri1_name) { + if (infoX->usriX_name) { fields_present |= SAMR_FIELD_FULL_NAME; } - if (info1->usri1_home_dir) { + if (infoX->usriX_home_dir) { fields_present |= SAMR_FIELD_HOME_DIRECTORY; } - if (info1->usri1_script_path) { + if (infoX->usriX_script_path) { fields_present |= SAMR_FIELD_LOGON_SCRIPT; } - if (info1->usri1_comment) { + if (infoX->usriX_comment) { fields_present |= SAMR_FIELD_DESCRIPTION; } - if (info1->usri1_password_age) { + if (infoX->usriX_password_age) { fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE; } - acct_flags |= info1->usri1_flags | ACB_NORMAL; + acct_flags |= infoX->usriX_flags | ACB_NORMAL; - unix_to_nt_time_abs(&password_age, info1->usri1_password_age); + unix_to_nt_time_abs(&password_age, infoX->usriX_password_age); - /* TODO: info1->usri1_priv */ - init_samr_user_info21(&info25->info, + /* TODO: infoX->usriX_priv */ + init_samr_user_info21(info21, 0, 0, 0, @@ -79,12 +78,12 @@ static void convert_USER_INFO_1_to_samr_user_info25(struct USER_INFO_1 *info1, 0, password_age, NULL, - info1->usri1_name, - info1->usri1_home_dir, + infoX->usriX_name, + infoX->usriX_home_dir, NULL, - info1->usri1_script_path, + infoX->usriX_script_path, NULL, - info1->usri1_comment, + infoX->usriX_comment, NULL, NULL, &zero_parameters, @@ -100,29 +99,80 @@ static void convert_USER_INFO_1_to_samr_user_info25(struct USER_INFO_1 *info1, 0, 0, 0); +} - if (info1->usri1_password) { - uchar pwbuf[532]; - struct MD5Context ctx; - uint8_t confounder[16]; - DATA_BLOB confounded_session_key = data_blob(NULL, 16); - - encode_pw_buffer(pwbuf, info1->usri1_password, STR_UNICODE); +/**************************************************************** +****************************************************************/ - generate_random_buffer((uint8_t *)confounder, 16); +static NTSTATUS construct_USER_INFO_X(uint32_t level, + uint8_t *buffer, + struct USER_INFO_X *uX) +{ + struct USER_INFO_0 *u0 = NULL; + struct USER_INFO_1 *u1 = NULL; + struct USER_INFO_2 *u2 = NULL; + struct USER_INFO_1007 *u1007 = NULL; - MD5Init(&ctx); - MD5Update(&ctx, confounder, 16); - MD5Update(&ctx, user_session_key->data, - user_session_key->length); - MD5Final(confounded_session_key.data, &ctx); + if (!buffer || !uX) { + return NT_STATUS_INVALID_PARAMETER; + } - SamOEMhashBlob(pwbuf, 516, &confounded_session_key); - memcpy(&pwbuf[516], confounder, 16); + ZERO_STRUCTP(uX); - memcpy(info25->password.data, pwbuf, sizeof(pwbuf)); - data_blob_free(&confounded_session_key); + switch (level) { + case 0: + u0 = (struct USER_INFO_0 *)buffer; + uX->usriX_name = u0->usri0_name; + break; + case 1: + u1 = (struct USER_INFO_1 *)buffer; + uX->usriX_name = u1->usri1_name; + uX->usriX_password = u1->usri1_password; + uX->usriX_password_age = u1->usri1_password_age; + uX->usriX_priv = u1->usri1_priv; + uX->usriX_home_dir = u1->usri1_home_dir; + uX->usriX_comment = u1->usri1_comment; + uX->usriX_flags = u1->usri1_flags; + uX->usriX_script_path = u1->usri1_script_path; + break; + case 2: + u2 = (struct USER_INFO_2 *)buffer; + uX->usriX_name = u2->usri2_name; + uX->usriX_password = u2->usri2_password; + uX->usriX_password_age = u2->usri2_password_age; + uX->usriX_priv = u2->usri2_priv; + uX->usriX_home_dir = u2->usri2_home_dir; + uX->usriX_comment = u2->usri2_comment; + uX->usriX_flags = u2->usri2_flags; + uX->usriX_script_path = u2->usri2_script_path; + uX->usriX_auth_flags = u2->usri2_auth_flags; + uX->usriX_full_name = u2->usri2_full_name; + uX->usriX_usr_comment = u2->usri2_usr_comment; + uX->usriX_parms = u2->usri2_parms; + uX->usriX_workstations = u2->usri2_workstations; + uX->usriX_last_logon = u2->usri2_last_logon; + uX->usriX_last_logoff = u2->usri2_last_logoff; + uX->usriX_acct_expires = u2->usri2_acct_expires; + uX->usriX_max_storage = u2->usri2_max_storage; + uX->usriX_units_per_week= u2->usri2_units_per_week; + uX->usriX_logon_hours = u2->usri2_logon_hours; + uX->usriX_bad_pw_count = u2->usri2_bad_pw_count; + uX->usriX_num_logons = u2->usri2_num_logons; + uX->usriX_logon_server = u2->usri2_logon_server; + uX->usriX_country_code = u2->usri2_country_code; + uX->usriX_code_page = u2->usri2_code_page; + break; + case 1007: + u1007 = (struct USER_INFO_1007 *)buffer; + uX->usriX_comment = u1007->usri1007_comment; + break; + case 3: + case 4: + default: + return NT_STATUS_INVALID_INFO_CLASS; } + + return NT_STATUS_OK; } /**************************************************************** @@ -138,12 +188,12 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx, POLICY_HND connect_handle, domain_handle, user_handle; struct lsa_String lsa_account_name; struct dom_sid2 *domain_sid = NULL; - struct samr_UserInfo25 info25; + struct samr_UserInfo21 info21; union samr_UserInfo *user_info = NULL; struct samr_PwInfo pw_info; uint32_t access_granted = 0; uint32_t rid = 0; - struct USER_INFO_1 *info1; + struct USER_INFO_X uX; ZERO_STRUCT(connect_handle); ZERO_STRUCT(domain_handle); @@ -155,7 +205,6 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx, switch (r->in.level) { case 1: - info1 = (struct USER_INFO_1 *)r->in.buffer; break; case 2: case 3: @@ -176,6 +225,12 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx, goto done; } + status = construct_USER_INFO_X(r->in.level, r->in.buffer, &uX); + if (!NT_STATUS_IS_OK(status)) { + werr = ntstatus_to_werror(status); + goto done; + } + werr = libnetapi_samr_open_domain(ctx, pipe_cli, SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_OPEN_DOMAIN, @@ -189,7 +244,7 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx, goto done; } - init_lsa_String(&lsa_account_name, info1->usri1_name); + init_lsa_String(&lsa_account_name, uX.usriX_name); status = rpccli_samr_CreateUser2(pipe_cli, ctx, &domain_handle, @@ -230,14 +285,36 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx, goto done; } + convert_USER_INFO_X_to_samr_user_info21(&uX, + &info21); + ZERO_STRUCTP(user_info); - convert_USER_INFO_1_to_samr_user_info25(info1, - &cli->user_session_key, - &info25); + if (uX.usriX_password) { + + uchar pwbuf[532]; + struct MD5Context md5_ctx; + uint8_t confounder[16]; + DATA_BLOB confounded_session_key = data_blob(NULL, 16); + + encode_pw_buffer(pwbuf, uX.usriX_password, STR_UNICODE); + + generate_random_buffer((uint8_t *)confounder, 16); + + MD5Init(&md5_ctx); + MD5Update(&md5_ctx, confounder, 16); + MD5Update(&md5_ctx, cli->user_session_key.data, + cli->user_session_key.length); + MD5Final(confounded_session_key.data, &md5_ctx); + + SamOEMhashBlob(pwbuf, 516, &confounded_session_key); + memcpy(&pwbuf[516], confounder, 16); + + memcpy(user_info->info25.password.data, pwbuf, sizeof(pwbuf)); + data_blob_free(&confounded_session_key); + + user_info->info25.info = info21; - if (info1->usri1_password) { - user_info->info25 = info25; status = rpccli_samr_SetUserInfo2(pipe_cli, ctx, &user_handle, 25, @@ -245,10 +322,10 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx, if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) { - user_info->info23.info = info25.info; + user_info->info23.info = info21; encode_pw_buffer(user_info->info23.password.data, - info1->usri1_password, STR_UNICODE); + uX.usriX_password, STR_UNICODE); SamOEMhashBlob(user_info->info23.password.data, 516, &cli->user_session_key); @@ -258,7 +335,7 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx, user_info); } } else { - user_info->info21 = info25.info; + user_info->info21 = info21; status = rpccli_samr_SetUserInfo(pipe_cli, ctx, &user_handle, 21, |