From 3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Dec 1999 13:27:58 +0000 Subject: first pass at updating head branch to be to be the same as the SAMBA_2_0 branch (This used to be commit 453a822a76780063dff23526c35408866d0c0154) --- source3/rpc_server/srv_lookup.c | 592 +++++--- source3/rpc_server/srv_lsa.c | 507 ++++--- source3/rpc_server/srv_lsa_hnd.c | 245 +-- source3/rpc_server/srv_netlog.c | 934 ++++++------ source3/rpc_server/srv_pipe.c | 1510 ++++++++++--------- source3/rpc_server/srv_pipe_hnd.c | 371 ++--- source3/rpc_server/srv_reg.c | 59 +- source3/rpc_server/srv_samr.c | 2962 ++++++++++--------------------------- source3/rpc_server/srv_srvsvc.c | 640 ++++---- source3/rpc_server/srv_util.c | 323 +++- source3/rpc_server/srv_wkssvc.c | 10 +- 11 files changed, 3409 insertions(+), 4744 deletions(-) (limited to 'source3/rpc_server') diff --git a/source3/rpc_server/srv_lookup.c b/source3/rpc_server/srv_lookup.c index 193c7931ab..e6df9933bf 100644 --- a/source3/rpc_server/srv_lookup.c +++ b/source3/rpc_server/srv_lookup.c @@ -52,6 +52,44 @@ extern fstring global_sam_name; extern DOM_SID global_sam_sid; extern DOM_SID global_sid_S_1_5_20; +/* + * A list of the rids of well known BUILTIN and Domain users + * and groups. + */ + +rid_name builtin_alias_rids[] = +{ + { BUILTIN_ALIAS_RID_ADMINS , "Administrators" }, + { BUILTIN_ALIAS_RID_USERS , "Users" }, + { BUILTIN_ALIAS_RID_GUESTS , "Guests" }, + { BUILTIN_ALIAS_RID_POWER_USERS , "Power Users" }, + + { BUILTIN_ALIAS_RID_ACCOUNT_OPS , "Account Operators" }, + { BUILTIN_ALIAS_RID_SYSTEM_OPS , "System Operators" }, + { BUILTIN_ALIAS_RID_PRINT_OPS , "Print Operators" }, + { BUILTIN_ALIAS_RID_BACKUP_OPS , "Backup Operators" }, + { BUILTIN_ALIAS_RID_REPLICATOR , "Replicator" }, + { 0 , NULL } +}; + +/* array lookup of well-known Domain RID users. */ +rid_name domain_user_rids[] = +{ + { DOMAIN_USER_RID_ADMIN , "Administrator" }, + { DOMAIN_USER_RID_GUEST , "Guest" }, + { 0 , NULL } +}; + +/* array lookup of well-known Domain RID groups. */ +rid_name domain_group_rids[] = +{ + { DOMAIN_GROUP_RID_ADMINS , "Domain Admins" }, + { DOMAIN_GROUP_RID_USERS , "Domain Users" }, + { DOMAIN_GROUP_RID_GUESTS , "Domain Guests" }, + { 0 , NULL } +}; + + int make_dom_gids(DOMAIN_GRP *mem, int num_members, DOM_GID **ppgids) { int count; @@ -72,27 +110,17 @@ int make_dom_gids(DOMAIN_GRP *mem, int num_members, DOM_GID **ppgids) uint32 status; uint32 rid; - DOM_SID sid; uint8 type; uint8 attr = mem[count].attr; char *name = mem[count].name; become_root(True); - status = lookup_name(name, &sid, &type); + status = lookup_grp_rid(name, &rid, &type); unbecome_root(True); - if (status == 0x0 && !sid_front_equal(&global_sam_sid, &sid)) - { - fstring sid_str; - sid_to_string(sid_str, &sid); - DEBUG(1,("make_dom_gids: unknown sid %s for groupname %s\n", - sid_str, name)); - } - else if (status == 0x0) + if (status == 0x0) { - sid_split_rid(&sid, &rid); - gids = (DOM_GID *)Realloc( gids, sizeof(DOM_GID) * (count+1) ); if (gids == NULL) @@ -110,7 +138,7 @@ int make_dom_gids(DOMAIN_GRP *mem, int num_members, DOM_GID **ppgids) } else { - DEBUG(1,("make_dom_gids: unknown groupname %s\n", name)); + DEBUG(1,("make_dom_gids: unknown group name %s\n", name)); } } @@ -140,286 +168,282 @@ int get_domain_user_groups(DOMAIN_GRP_MEMBER **grp_members, uint32 group_rid) /******************************************************************* - lookup_builtin_sid + lookup_builtin_names ********************************************************************/ -uint32 lookup_builtin_sid(DOM_SID *sid, char *name, uint8 *type) +uint32 lookup_builtin_names(uint32 rid, char *name, uint8 *type) { uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - status = (status != 0x0) ? lookup_wk_user_sid (sid, name, type) : status; - status = (status != 0x0) ? lookup_wk_group_sid(sid, name, type) : status; - status = (status != 0x0) ? lookup_wk_alias_sid(sid, name, type) : status; + status = (status != 0x0) ? lookup_wk_user_name (rid, name, type) : status; + status = (status != 0x0) ? lookup_wk_group_name(rid, name, type) : status; + status = (status != 0x0) ? lookup_wk_alias_name(rid, name, type) : status; return status; } /******************************************************************* - lookup_added_sid - names that have been added to the SAM database by admins. + lookup_added_name - names that have been added to the SAM database by admins. ********************************************************************/ -uint32 lookup_added_sid(DOM_SID *sid, char *name, uint8 *type) +uint32 lookup_added_name(uint32 rid, char *name, uint8 *type) { uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - status = (status != 0x0) ? lookup_user_sid (sid, name, type) : status; - status = (status != 0x0) ? lookup_group_sid(sid, name, type) : status; - status = (status != 0x0) ? lookup_alias_sid(sid, name, type) : status; + status = (status != 0x0) ? lookup_user_name (rid, name, type) : status; + status = (status != 0x0) ? lookup_group_name(rid, name, type) : status; + status = (status != 0x0) ? lookup_alias_name(rid, name, type) : status; return status; } /******************************************************************* - lookup_sid + lookup_name ********************************************************************/ -uint32 lookup_sid(DOM_SID *sid, char *name, uint8 *type) +uint32 lookup_name(uint32 rid, char *name, uint8 *type) { uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - status = (status != 0x0) ? lookup_builtin_sid(sid, name, type) : status; - status = (status != 0x0) ? lookup_added_sid (sid, name, type) : status; + status = (status != 0x0) ? lookup_builtin_names(rid, name, type) : status; + status = (status != 0x0) ? lookup_added_name (rid, name, type) : status; return status; } /******************************************************************* - lookup_wk_group_sid + lookup_wk_group_name ********************************************************************/ -uint32 lookup_wk_group_sid(DOM_SID *sid, char *group_name, uint8 *type) +uint32 lookup_wk_group_name(uint32 rid, char *group_name, uint8 *type) { - uint32 rid; - DOM_SID tmp; - char *mapped; + int i = 0; + (*type) = SID_NAME_WKN_GRP; - (*type) = SID_NAME_DOM_GRP; - - sid_copy(&tmp, sid); - sid_split_rid(&tmp, &rid); + DEBUG(5,("lookup_wk_group_name: rid: %d", rid)); - if (!sid_equal(&global_sid_S_1_5_20, &tmp)) + while (domain_group_rids[i].rid != rid && domain_group_rids[i].rid != 0) { - return 0xC0000000 | NT_STATUS_NONE_MAPPED; + i++; } - DEBUG(5,("lookup_wk_group_sid: rid: %d", rid)); - - /* look up the well-known domain group rids first */ - mapped = lookup_wk_group_rid(rid); - if(mapped == NULL) + if (domain_group_rids[i].rid != 0) { - DEBUG(5,(" none mapped\n")); - return 0xC0000000 | NT_STATUS_NONE_MAPPED; + fstrcpy(group_name, domain_group_rids[i].name); + DEBUG(5,(" = %s\n", group_name)); + return 0x0; } - fstrcpy(group_name, mapped); - DEBUG(5,(" = %s\n", group_name)); - return 0x0; + + DEBUG(5,(" none mapped\n")); + return 0xC0000000 | NT_STATUS_NONE_MAPPED; } /******************************************************************* - lookup_group_sid + lookup_group_name ********************************************************************/ -uint32 lookup_group_sid(DOM_SID *sid, char *group_name, uint8 *type) +uint32 lookup_group_name(uint32 rid, char *group_name, uint8 *type) { - pstring sid_str; - uint32 rid; - DOM_SID tmp; - DOMAIN_GRP *grp = NULL; uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; + DOM_SID sid; - (*type) = SID_NAME_DOM_GRP; + DEBUG(5,("lookup_group_name: rid: 0x%x", rid)); - sid_to_string(sid_str, sid); - DEBUG(5,("lookup_group_sid: sid: %s", sid_str)); + sid_copy (&sid, &global_sam_sid); + sid_append_rid(&sid, rid); - sid_copy(&tmp, sid); - sid_split_rid(&tmp, &rid); + (*type) = SID_NAME_DOM_GRP; - if (!sid_equal(&global_sam_sid, &tmp)) + if (map_group_sid_to_name(&sid, group_name, NULL)) { - DEBUG(5,("not our SID\n")); - return 0xC0000000 | NT_STATUS_NONE_MAPPED; + status = 0x0; } - grp = getgrouprid(rid, NULL, NULL); - - if (grp != NULL) + if (status == 0x0) { - fstrcpy(group_name, grp->name); DEBUG(5,(" = %s\n", group_name)); - return 0x0; + } + else + { + DEBUG(5,(" none mapped\n")); } - DEBUG(5,(" none mapped\n")); return status; } /******************************************************************* - lookup_wk_alias_sid + lookup_wk_alias_name ********************************************************************/ -uint32 lookup_wk_alias_sid(DOM_SID *sid, char *alias_name, uint8 *type) +uint32 lookup_wk_alias_name(uint32 rid, char *alias_name, uint8 *type) { - uint32 rid; - DOM_SID tmp; - char *mapped; - + int i = 0; (*type) = SID_NAME_ALIAS; - sid_copy(&tmp, sid); - sid_split_rid(&tmp, &rid); + DEBUG(5,("lookup_wk_alias_name: rid: %d", rid)); - if (!sid_equal(&global_sid_S_1_5_20, &tmp)) + while (builtin_alias_rids[i].rid != rid && builtin_alias_rids[i].rid != 0) { - return 0xC0000000 | NT_STATUS_NONE_MAPPED; + i++; } - DEBUG(5,("lookup_wk_alias_sid: rid: %d", rid)); - - /* look up the well-known alias group rids first */ - mapped = lookup_wk_alias_rid(rid); - if(mapped == NULL) + if (builtin_alias_rids[i].rid != 0) { - DEBUG(5,(" none mapped\n")); - return 0xC0000000 | NT_STATUS_NONE_MAPPED; + fstrcpy(alias_name, builtin_alias_rids[i].name); + DEBUG(5,(" = %s\n", alias_name)); + return 0x0; } - fstrcpy(alias_name, mapped); - DEBUG(5,(" = %s\n", alias_name)); - return 0x0; + + DEBUG(5,(" none mapped\n")); + return 0xC0000000 | NT_STATUS_NONE_MAPPED; } /******************************************************************* - lookup_alias_sid + lookup_alias_name ********************************************************************/ -uint32 lookup_alias_sid(DOM_SID *sid, char *alias_name, uint8 *type) +uint32 lookup_alias_name(uint32 rid, char *alias_name, uint8 *type) { - pstring sid_str; - uint32 rid; - DOM_SID tmp; - LOCAL_GRP *als = NULL; - uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - (*type) = SID_NAME_ALIAS; - sid_to_string(sid_str, sid); - DEBUG(5,("lookup_alias_sid: sid: %s", sid_str)); + DEBUG(2,("lookup_alias_name: rid: %d\n", rid)); + DEBUG(2,(" NOT IMPLEMENTED\n")); - sid_copy(&tmp, sid); - sid_split_rid(&tmp, &rid); + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} - if (!sid_equal(&global_sam_sid, &tmp)) +/******************************************************************* + lookup well-known user name + ********************************************************************/ +uint32 lookup_wk_user_name(uint32 rid, char *user_name, uint8 *type) +{ + int i = 0; + (*type) = SID_NAME_USER; + + DEBUG(5,("lookup_wk_user_name: rid: %d", rid)); + + /* look up the well-known domain user rids first */ + while (domain_user_rids[i].rid != rid && domain_user_rids[i].rid != 0) { - DEBUG(5,("not our SID\n")); - return 0xC0000000 | NT_STATUS_NONE_MAPPED; + i++; } - als = getaliasrid(rid, NULL, NULL); - - if (als != NULL) + if (domain_user_rids[i].rid != 0) { - fstrcpy(alias_name, als->name); - DEBUG(5,(" = %s\n", alias_name)); + fstrcpy(user_name, domain_user_rids[i].name); + DEBUG(5,(" = %s\n", user_name)); return 0x0; } DEBUG(5,(" none mapped\n")); - return status; + return 0xC0000000 | NT_STATUS_NONE_MAPPED; } /******************************************************************* - lookup well-known user name + lookup user name ********************************************************************/ -uint32 lookup_wk_user_sid(DOM_SID *sid, char *user_name, uint8 *type) +uint32 lookup_user_name(uint32 rid, char *user_name, uint8 *type) { - uint32 rid; - DOM_SID tmp; - char *mapped; - + struct sam_disp_info *disp_info; (*type) = SID_NAME_USER; - sid_copy(&tmp, sid); - sid_split_rid(&tmp, &rid); + DEBUG(5,("lookup_user_name: rid: %d", rid)); - if (!sid_equal(&global_sid_S_1_5_20, &tmp)) + /* find the user account */ + become_root(True); + disp_info = getsamdisprid(rid); + unbecome_root(True); + + if (disp_info != NULL) { - return 0xC0000000 | NT_STATUS_NONE_MAPPED; + fstrcpy(user_name, disp_info->smb_name); + DEBUG(5,(" = %s\n", user_name)); + return 0x0; } - DEBUG(5,("lookup_wk_user_sid: rid: %d", rid)); + DEBUG(5,(" none mapped\n")); + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} - /* look up the well-known domain user rids first */ - mapped = lookup_wk_user_rid(rid); - if(mapped == NULL) +/******************************************************************* + lookup_group_rid + ********************************************************************/ +uint32 lookup_group_rid(char *group_name, uint32 *rid, uint8 *type) +{ + DOM_SID sid; + + (*rid) = 0; + (*type) = SID_NAME_DOM_GRP; + + DEBUG(5,("lookup_group_rid: name: %s", group_name)); + + if (map_group_name_to_sid(group_name, &sid) && + sid_split_rid(&sid, rid) && + sid_equal(&sid, &global_sam_sid)) { - DEBUG(5,(" none mapped\n")); - return 0xC0000000 | NT_STATUS_NONE_MAPPED; + DEBUG(5,(" = 0x%x\n", (*rid))); + return 0x0; } - fstrcpy(user_name, mapped); - DEBUG(5,(" = %s\n", user_name)); - return 0x0; + + DEBUG(5,(" none mapped\n")); + return 0xC0000000 | NT_STATUS_NONE_MAPPED; } /******************************************************************* - lookup user name + lookup_wk_group_rid ********************************************************************/ -uint32 lookup_user_sid(DOM_SID *sid, char *user_name, uint8 *type) +uint32 lookup_wk_group_rid(char *group_name, uint32 *rid, uint8 *type) { - struct sam_disp_info *disp_info; - uint32 rid; - DOM_SID tmp; + char *grp_name; + int i = -1; /* start do loop at -1 */ + (*rid) = 0; + (*type) = SID_NAME_WKN_GRP; - (*type) = SID_NAME_USER; + do /* find, if it exists, a group rid for the group name */ + { + i++; + (*rid) = domain_group_rids[i].rid; + grp_name = domain_group_rids[i].name; - sid_copy(&tmp, sid); - sid_split_rid(&tmp, &rid); + } while (grp_name != NULL && !strequal(grp_name, group_name)); - if (sid_equal(&global_sam_sid, &tmp)) - { - DEBUG(5,("lookup_user_sid in SAM %s: rid: %d", - global_sam_name, rid)); + return (grp_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED; +} - /* find the user account */ - become_root(True); - disp_info = getsamdisprid(rid); - unbecome_root(True); +/******************************************************************* + lookup_alias_sid + ********************************************************************/ +uint32 lookup_alias_sid(char *alias_name, DOM_SID *sid, uint8 *type) +{ + (*type) = SID_NAME_ALIAS; - if (disp_info != NULL) - { - fstrcpy(user_name, disp_info->nt_name); - DEBUG(5,(" = %s\n", user_name)); - return 0x0; - } + DEBUG(5,("lookup_alias_rid: name: %s", alias_name)); - DEBUG(5,(" none mapped\n")); + if (map_alias_name_to_sid(alias_name, sid)) + { + fstring sid_str; + sid_to_string(sid_str, sid); + DEBUG(5,(" = %s\n", sid_str)); + return 0x0; } + DEBUG(5,(" none mapped\n")); return 0xC0000000 | NT_STATUS_NONE_MAPPED; } /******************************************************************* - lookup_group_rid + lookup_alias_rid ********************************************************************/ -uint32 lookup_added_group_name(const char *grp_name, const char *domain, - DOM_SID *sid, uint8 *type) +uint32 lookup_alias_rid(char *alias_name, uint32 *rid, uint8 *type) { - DOMAIN_GRP *grp = NULL; - (*type) = SID_NAME_DOM_GRP; - - DEBUG(5,("lookup_added_group_name: name: %s", grp_name)); + DOM_SID sid; - if (!strequal(domain, global_sam_name)) - { - DEBUG(5,(" not our domain\n")); - return 0xC0000000 | NT_STATUS_NONE_MAPPED; - } + (*rid) = 0; + (*type) = SID_NAME_ALIAS; - grp = getgroupntnam(grp_name, NULL, NULL); + DEBUG(5,("lookup_alias_rid: name: %s", alias_name)); - if (grp != NULL) + if (map_alias_name_to_sid(alias_name, &sid) && + sid_split_rid(&sid, rid) && + sid_equal(&sid, &global_sam_sid)) { - sid_copy(sid, &global_sam_sid); - sid_append_rid(sid, grp->rid); - - DEBUG(5,(" = 0x%x\n", grp->rid)); + DEBUG(5,(" = 0x%x\n", (*rid))); return 0x0; } @@ -428,41 +452,86 @@ uint32 lookup_added_group_name(const char *grp_name, const char *domain, } /******************************************************************* - lookup_added_alias_name + lookup_wk_alias_sid ********************************************************************/ -uint32 lookup_added_alias_name(const char *als_name, const char *domain, - DOM_SID *sid, uint8 *type) +uint32 lookup_wk_alias_sid(char *alias_name, DOM_SID *sid, uint8 *type) { - LOCAL_GRP *als = NULL; + char *als_name; + int i = 0; + uint32 rid; (*type) = SID_NAME_ALIAS; - DEBUG(5,("lookup_added_alias_name: name: %s\\%s", domain, als_name)); - - if (!strequal(domain, global_sam_name)) + do /* find, if it exists, a alias rid for the alias name*/ { - DEBUG(5,(" not our domain\n")); - return 0xC0000000 | NT_STATUS_NONE_MAPPED; - } + rid = builtin_alias_rids[i].rid; + als_name = builtin_alias_rids[i].name; - als = getaliasntnam(als_name, NULL, NULL); + i++; - if (als != NULL) + if (strequal(als_name, alias_name)) + { + sid_copy(sid, &global_sid_S_1_5_20); + sid_append_rid(sid, rid); + + return 0x0; + } + + } while (als_name != NULL); + + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_wk_alias_rid + ********************************************************************/ +uint32 lookup_wk_alias_rid(char *alias_name, uint32 *rid, uint8 *type) +{ + char *als_name; + int i = -1; /* start do loop at -1 */ + (*rid) = 0; + (*type) = SID_NAME_ALIAS; + + do /* find, if it exists, a alias rid for the alias name*/ { - sid_copy(sid, &global_sam_sid); - sid_append_rid(sid, als->rid); + i++; + (*rid) = builtin_alias_rids[i].rid; + als_name = builtin_alias_rids[i].name; - DEBUG(5,(" = 0x%x\n", als->rid)); - return 0x0; + } while (als_name != NULL && !strequal(als_name, alias_name)); + + return (als_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_sid + ********************************************************************/ +uint32 lookup_sid(char *name, DOM_SID *sid, uint8 *type) +{ + uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; + fstring domain; + fstring user; + + split_domain_name(name, domain, user); + + if (!strequal(domain, global_sam_name)) + { + DEBUG(0,("lookup_sid: remote domain %s not supported\n", domain)); + return status; } - DEBUG(5,(" none mapped\n")); - return 0xC0000000 | NT_STATUS_NONE_MAPPED; + status = (status != 0x0) ? lookup_wk_alias_sid(user, sid, type) : status; + status = (status != 0x0) ? lookup_alias_sid (user, sid, type) : status; +#if 0 + status = (status != 0x0) ? lookup_domain_sid (user, sid, type) : status; +#endif + + return status; } /******************************************************************* lookup_added_user_rid ********************************************************************/ -uint32 lookup_added_user_rids(char *nt_name, +uint32 lookup_added_user_rids(char *user_name, uint32 *usr_rid, uint32 *grp_rid) { struct sam_passwd *sam_pass; @@ -471,7 +540,7 @@ uint32 lookup_added_user_rids(char *nt_name, /* find the user account */ become_root(True); - sam_pass = getsam21pwntnam(nt_name); + sam_pass = getsam21pwnam(user_name); unbecome_root(True); if (sam_pass != NULL) @@ -485,29 +554,22 @@ uint32 lookup_added_user_rids(char *nt_name, } /******************************************************************* - lookup_added_user_name + lookup_added_user_rid ********************************************************************/ -static uint32 lookup_added_user_name(const char *nt_name, const char *domain, - DOM_SID *sid, uint8 *type) +uint32 lookup_added_user_rid(char *user_name, uint32 *rid, uint8 *type) { struct sam_passwd *sam_pass; + (*rid) = 0; (*type) = SID_NAME_USER; - if (!strequal(domain, global_sam_name)) - { - return 0xC0000000 | NT_STATUS_NONE_MAPPED; - } - /* find the user account */ become_root(True); - sam_pass = getsam21pwntnam(nt_name); + sam_pass = getsam21pwnam(user_name); unbecome_root(True); if (sam_pass != NULL) { - sid_copy(sid, &global_sam_sid); - sid_append_rid(sid, sam_pass->user_rid); - + (*rid) = sam_pass->user_rid; return 0x0; } @@ -515,52 +577,134 @@ static uint32 lookup_added_user_name(const char *nt_name, const char *domain, } /******************************************************************* - lookup_grp_name + lookup_wk_user_rid ********************************************************************/ -static uint32 lookup_grp_name(const char *name, const char *domain, - DOM_SID *sid, uint8 *type) +uint32 lookup_wk_user_rid(char *user_name, uint32 *rid, uint8 *type) +{ + char *usr_name; + int i = -1; /* start do loop at -1 */ + (*rid) = 0; + (*type) = SID_NAME_USER; + + do /* find, if it exists, a alias rid for the alias name*/ + { + i++; + (*rid) = domain_user_rids[i].rid; + usr_name = domain_user_rids[i].name; + + } while (usr_name != NULL && !strequal(usr_name, user_name)); + + return (usr_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_added_grp_rid + ********************************************************************/ +uint32 lookup_added_grp_rid(char *name, uint32 *rid, uint8 *type) { uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - status = (status != 0x0) ? lookup_wk_group_name (name, domain, sid, type) : status; - status = (status != 0x0) ? lookup_builtin_alias_name(name, domain, sid, type) : status; - status = (status != 0x0) ? lookup_added_group_name (name, domain, sid, type) : status; - status = (status != 0x0) ? lookup_added_alias_name (name, domain, sid, type) : status; + status = (status != 0x0) ? lookup_group_rid(name, rid, type) : status; + status = (status != 0x0) ? lookup_alias_rid(name, rid, type) : status; return status; } /******************************************************************* - lookup_user_name + lookup_builtin_grp_rid ********************************************************************/ -static uint32 lookup_user_name(const char *name, const char *domain, - DOM_SID *sid, uint8 *type) +uint32 lookup_builtin_grp_rid(char *name, uint32 *rid, uint8 *type) { uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - status = (status != 0x0) ? lookup_wk_user_name (name, domain, sid, type) : status; - status = (status != 0x0) ? lookup_added_user_name(name, domain, sid, type) : status; + status = (status != 0x0) ? lookup_wk_group_rid(name, rid, type) : status; + status = (status != 0x0) ? lookup_wk_alias_rid(name, rid, type) : status; return status; } /******************************************************************* - lookup_name + lookup_grp_rid ********************************************************************/ -uint32 lookup_name(char *name, DOM_SID *sid, uint8 *type) +uint32 lookup_grp_rid(char *name, uint32 *rid, uint8 *type) { uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - fstring domain; - fstring user; - - split_domain_name(name, domain, user); - status = (status != 0x0) ? lookup_user_name (user, domain, sid, type) : status; - status = (status != 0x0) ? lookup_grp_name (user, domain, sid, type) : status; -#if 0 - status = (status != 0x0) ? lookup_domain_name (domain, sid, type) : status; -#endif + status = (status != 0x0) ? lookup_builtin_grp_rid(name, rid, type) : status; + status = (status != 0x0) ? lookup_added_grp_rid (name, rid, type) : status; return status; } +/******************************************************************* + lookup_user_rid + ********************************************************************/ +uint32 lookup_user_rid(char *name, uint32 *rid, uint8 *type) +{ + uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; + + status = (status != 0x0) ? lookup_wk_user_rid (name, rid, type) : status; + status = (status != 0x0) ? lookup_added_user_rid(name, rid, type) : status; + + return status; +} + +/******************************************************************* + lookup_rid + ********************************************************************/ +uint32 lookup_rid(char *name, uint32 *rid, uint8 *type) +{ + uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; + + status = (status != 0x0) ? lookup_user_rid(name, rid, type) : status; + status = (status != 0x0) ? lookup_grp_rid (name, rid, type) : status; + + return status; +} + +/******************************************************************* + lookup_user_rids + ********************************************************************/ +uint32 lookup_user_rids(char *name, uint32 *usr_rid, uint32 *grp_rid) +{ + uint32 status = 0xC0000000 | NT_STATUS_NONE_MAPPED; + uint8 type; + + /* + * try an ordinary user lookup + */ + + status = lookup_added_user_rids(name, usr_rid, grp_rid); + if (status == 0) + { + return status; + } + + /* + * hm. must be a well-known user, in a well-known group. + */ + + status = lookup_wk_user_rid(name, usr_rid, &type); + if (status != 0 || type != SID_NAME_USER) + { + return status; /* ok, maybe not! */ + } + if (type != SID_NAME_USER) + { + return 0xC0000000 | NT_STATUS_NONE_MAPPED; /* users only... */ + } + + /* + * ok, got the user rid: now try the group rid + */ + + status = lookup_builtin_grp_rid(name, grp_rid, &type); + if (type == SID_NAME_DOM_GRP || + type == SID_NAME_ALIAS || + type == SID_NAME_WKN_GRP) + { + status = 0xC0000000 | NT_STATUS_NONE_MAPPED; + } + + return status; +} diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c index fbe83b02c8..7094d842b4 100644 --- a/source3/rpc_server/srv_lsa.c +++ b/source3/rpc_server/srv_lsa.c @@ -29,82 +29,87 @@ extern int DEBUGLEVEL; extern DOM_SID global_sam_sid; -extern fstring global_sam_name; -extern DOM_SID global_member_sid; extern fstring global_myworkgroup; -extern DOM_SID global_sid_S_1_5_20; +extern pstring global_myname; /*************************************************************************** -lsa_reply_open_policy2 + lsa_reply_open_policy2 ***************************************************************************/ -static void lsa_reply_open_policy2(prs_struct *rdata) + +static BOOL lsa_reply_open_policy2(prs_struct *rdata) { + int i; LSA_R_OPEN_POL2 r_o; ZERO_STRUCT(r_o); /* set up the LSA QUERY INFO response */ + for (i = 4; i < POL_HND_SIZE; i++) + r_o.pol.data[i] = i; r_o.status = 0x0; - /* get a (unique) handle. open a policy on it. */ - if (!open_policy_hnd(&r_o.pol)) - { - r_o.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + /* store the response in the SMB stream */ + if(!lsa_io_r_open_pol2("", &r_o, rdata, 0)) { + DEBUG(0,("lsa_reply_open_policy2: unable to marshall LSA_R_OPEN_POL2.\n")); + return False; } - /* store the response in the SMB stream */ - lsa_io_r_open_pol2("", &r_o, rdata, 0); + return True; } /*************************************************************************** lsa_reply_open_policy ***************************************************************************/ -static void lsa_reply_open_policy(prs_struct *rdata) + +static BOOL lsa_reply_open_policy(prs_struct *rdata) { + int i; LSA_R_OPEN_POL r_o; ZERO_STRUCT(r_o); /* set up the LSA QUERY INFO response */ + for (i = 4; i < POL_HND_SIZE; i++) + r_o.pol.data[i] = i; r_o.status = 0x0; - /* get a (unique) handle. open a policy on it. */ - if (!open_policy_hnd(&r_o.pol)) - { - r_o.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + /* store the response in the SMB stream */ + if(!lsa_io_r_open_pol("", &r_o, rdata, 0)) { + DEBUG(0,("lsa_reply_open_policy: unable to marshall LSA_R_OPEN_POL.\n")); + return False; } - /* store the response in the SMB stream */ - lsa_io_r_open_pol("", &r_o, rdata, 0); + return True; } /*************************************************************************** -make_dom_query +Init dom_query ***************************************************************************/ -static void make_dom_query(DOM_QUERY *d_q, char *dom_name, DOM_SID *dom_sid) + +static void init_dom_query(DOM_QUERY *d_q, char *dom_name, DOM_SID *dom_sid) { fstring sid_str; int domlen = strlen(dom_name); - d_q->uni_dom_str_len = (domlen+1) * 2; d_q->uni_dom_max_len = domlen * 2; + d_q->uni_dom_str_len = domlen * 2; d_q->buffer_dom_name = domlen != 0 ? 1 : 0; /* domain buffer pointer */ d_q->buffer_dom_sid = dom_sid != NULL ? 1 : 0; /* domain sid pointer */ /* this string is supposed to be character short */ - make_unistr2(&(d_q->uni_domain_name), dom_name, domlen); - d_q->uni_domain_name.uni_max_len++; + init_unistr2(&d_q->uni_domain_name, dom_name, domlen); sid_to_string(sid_str, dom_sid); - make_dom_sid2(&(d_q->dom_sid), dom_sid); + init_dom_sid2(&d_q->dom_sid, dom_sid); } /*************************************************************************** -lsa_reply_query_info + lsa_reply_enum_trust_dom ***************************************************************************/ + static void lsa_reply_enum_trust_dom(LSA_Q_ENUM_TRUST_DOM *q_e, prs_struct *rdata, uint32 enum_context, char *dom_name, DOM_SID *dom_sid) @@ -114,7 +119,7 @@ static void lsa_reply_enum_trust_dom(LSA_Q_ENUM_TRUST_DOM *q_e, ZERO_STRUCT(r_e); /* set up the LSA QUERY INFO response */ - make_r_enum_trust_dom(&r_e, enum_context, dom_name, dom_sid, + init_r_enum_trust_dom(&r_e, enum_context, dom_name, dom_sid, dom_name != NULL ? 0x0 : 0x80000000 | NT_STATUS_UNABLE_TO_FREE_VM); /* store the response in the SMB stream */ @@ -124,63 +129,53 @@ static void lsa_reply_enum_trust_dom(LSA_Q_ENUM_TRUST_DOM *q_e, /*************************************************************************** lsa_reply_query_info ***************************************************************************/ -static void lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, prs_struct *rdata, + +static BOOL lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, prs_struct *rdata, char *dom_name, DOM_SID *dom_sid) { LSA_R_QUERY_INFO r_q; ZERO_STRUCT(r_q); - /* get a (unique) handle. open a policy on it. */ - if (r_q.status == 0x0 && !open_policy_hnd(&q_q->pol)) - { - r_q.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - else - { - /* set up the LSA QUERY INFO response */ + /* set up the LSA QUERY INFO response */ - r_q.undoc_buffer = 0x1; - r_q.info_class = q_q->info_class; + r_q.undoc_buffer = 0x22000000; /* bizarre */ + r_q.info_class = q_q->info_class; - make_dom_query(&r_q.dom.id5, dom_name, dom_sid); + init_dom_query(&r_q.dom.id5, dom_name, dom_sid); + + r_q.status = 0x0; - r_q.status = 0x0; - } /* store the response in the SMB stream */ - lsa_io_r_query("", &r_q, rdata, 0); -} + if(!lsa_io_r_query("", &r_q, rdata, 0)) { + DEBUG(0,("lsa_reply_query_info: failed to marshall LSA_R_QUERY_INFO.\n")); + return False; + } + return True; +} /*************************************************************************** -make_dom_ref - adds a domain if it's not already in, returns the index - ***************************************************************************/ -static int make_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid) - + init_dom_ref - adds a domain if it's not already in, returns the index. +***************************************************************************/ + +static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid) { int num = 0; int len; - if (dom_name != NULL) - { - for (num = 0; num < ref->num_ref_doms_1; num++) - { + if (dom_name != NULL) { + for (num = 0; num < ref->num_ref_doms_1; num++) { fstring domname; - unistr2_to_ascii(domname, &ref->ref_dom[num].uni_dom_name, sizeof(domname)-1); + fstrcpy(domname, dos_unistr2_to_str(&ref->ref_dom[num].uni_dom_name)); if (strequal(domname, dom_name)) - { return num; - } } - - } - else - { + } else { num = ref->num_ref_doms_1; } - if (num >= MAX_REF_DOMAINS) - { + if (num >= MAX_REF_DOMAINS) { /* index not found, already at maximum domain limit */ return -1; } @@ -190,95 +185,85 @@ static int make_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid) ref->max_entries = MAX_REF_DOMAINS; ref->num_ref_doms_2 = num+1; - len = dom_name != NULL ? strlen(dom_name) : 0; + len = (dom_name != NULL) ? strlen(dom_name) : 0; + if(dom_name != NULL && len == 0) + len = 1; - make_uni_hdr(&(ref->hdr_ref_dom[num].hdr_dom_name), len); + init_uni_hdr(&ref->hdr_ref_dom[num].hdr_dom_name, len); ref->hdr_ref_dom[num].ptr_dom_sid = dom_sid != NULL ? 1 : 0; - make_unistr2 (&(ref->ref_dom[num].uni_dom_name), dom_name, len); - make_dom_sid2(&(ref->ref_dom[num].ref_dom ), dom_sid ); + init_unistr2(&ref->ref_dom[num].uni_dom_name, dom_name, len); + init_dom_sid2(&ref->ref_dom[num].ref_dom, dom_sid ); return num; } /*************************************************************************** -make_lsa_rid2s + init_lsa_rid2s ***************************************************************************/ -static void make_lsa_rid2s(DOM_R_REF *ref, - DOM_RID2 *rid2, + +static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2, int num_entries, UNISTR2 name[MAX_LOOKUP_SIDS], uint32 *mapped_count) { int i; int total = 0; - (*mapped_count) = 0; + *mapped_count = 0; SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS); - for (i = 0; i < num_entries; i++) - { - uint32 status = 0x0; - DOM_SID find_sid; + for (i = 0; i < num_entries; i++) { + BOOL status = False; + DOM_SID dom_sid; DOM_SID sid; uint32 rid = 0xffffffff; int dom_idx = -1; - fstring find_name; - char *dom_name = NULL; + pstring full_name; + fstring dom_name; + fstring user; uint8 sid_name_use = SID_NAME_UNKNOWN; - unistr2_to_ascii(find_name, &name[i], sizeof(find_name)-1); - dom_name = strdup(find_name); + pstrcpy(full_name, dos_unistr2_to_str(&name[i])); - if (map_domain_name_to_sid(&sid, &dom_name)) - { - sid_name_use = SID_NAME_DOMAIN; - dom_idx = make_dom_ref(ref, dom_name, &find_sid); - } + /* + * Try and split the name into a DOMAIN and + * user component. + */ - if (lookup_name(find_name, &sid, &sid_name_use) == 0x0 && - sid_split_rid(&sid, &rid)) - { - if (map_domain_sid_to_name(&sid, find_name)) - { - dom_idx = make_dom_ref(ref, find_name, &sid); - } - else - { - status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - } - } - else - { - status = 0xC0000000 | NT_STATUS_NONE_MAPPED; + split_domain_name(full_name, dom_name, user); + + /* + * We only do anything with this name if we + * can map the Domain into a SID we know. + */ + + if (map_domain_name_to_sid(&dom_sid, dom_name)) { + dom_idx = init_dom_ref(ref, dom_name, &dom_sid); + + if (lookup_local_name(dom_name, user, &sid, &sid_name_use) && sid_split_rid(&sid, &rid)) + status = True; } - if (status == 0x0) - { + if (status) (*mapped_count)++; - } - else - { + else { dom_idx = -1; rid = 0xffffffff; sid_name_use = SID_NAME_UNKNOWN; } - make_dom_rid2(&rid2[total], rid, sid_name_use, dom_idx); + init_dom_rid2(&rid2[total], rid, sid_name_use, dom_idx); total++; - - if (dom_name != NULL) - { - free(dom_name); - } } } /*************************************************************************** -make_reply_lookup_names + init_reply_lookup_names ***************************************************************************/ -static void make_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l, - DOM_R_REF *ref, uint32 num_entries, - DOM_RID2 *rid2, uint32 mapped_count) + +static void init_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l, + DOM_R_REF *ref, uint32 num_entries, + DOM_RID2 *rid2, uint32 mapped_count) { r_l->ptr_dom_ref = 1; r_l->dom_ref = ref; @@ -291,84 +276,74 @@ static void make_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l, r_l->mapped_count = mapped_count; if (mapped_count == 0) - { r_l->status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - } else - { r_l->status = 0x0; - } } /*************************************************************************** -make_lsa_trans_names + Init lsa_trans_names. ***************************************************************************/ -static void make_lsa_trans_names(DOM_R_REF *ref, - LSA_TRANS_NAME_ENUM *trn, - int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS], - uint32 *mapped_count) + +static void init_lsa_trans_names(DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *trn, + int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS], uint32 *mapped_count) { + extern DOM_SID global_sid_S_1_5_0x20; /* BUILTIN sid. */ int i; int total = 0; - (*mapped_count) = 0; + *mapped_count = 0; SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS); - for (i = 0; i < num_entries; i++) - { - uint32 status = 0x0; + for (i = 0; i < num_entries; i++) { + BOOL status = False; DOM_SID find_sid = sid[i].sid; - DOM_SID tmp_sid = sid[i].sid; uint32 rid = 0xffffffff; int dom_idx = -1; fstring name; fstring dom_name; uint8 sid_name_use = 0; - - memset(dom_name, 0, sizeof(dom_name)); - memset(name , 0, sizeof(name )); - if (map_domain_sid_to_name(&find_sid, dom_name)) - { + memset(dom_name, '\0', sizeof(dom_name)); + memset(name, '\0', sizeof(name)); + + /* + * First, check to see if the SID is one of the well + * known ones (this includes our own domain SID). + * Next, check if the domain prefix is one of the + * well known ones. If so and the domain prefix was + * either BUILTIN or our own global sid, then lookup + * the RID as a user or group id and translate to + * a name. + */ + + if (map_domain_sid_to_name(&find_sid, dom_name)) { sid_name_use = SID_NAME_DOMAIN; - dom_idx = make_dom_ref(ref, dom_name, &find_sid); - } - else if (sid_split_rid (&find_sid, &rid) && - map_domain_sid_to_name(&find_sid, dom_name)) - { + } else if (sid_split_rid(&find_sid, &rid) && map_domain_sid_to_name(&find_sid, dom_name)) { if (sid_equal(&find_sid, &global_sam_sid) || - sid_equal(&find_sid, &global_sid_S_1_5_20)) - { - /* lkclXXXX REPLACE THIS FUNCTION WITH - samr_xxxx() routines - */ - status = lookup_sid(&tmp_sid, name, &sid_name_use); + sid_equal(&find_sid, &global_sid_S_1_5_0x20)) { + status = lookup_local_rid(rid, name, &sid_name_use); + } else { + status = lookup_known_rid(&find_sid, rid, name, &sid_name_use); } - else - { - status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - } - } - else - { - status = 0xC0000000 | NT_STATUS_NONE_MAPPED; } - dom_idx = make_dom_ref(ref, dom_name, &find_sid); + DEBUG(10,("init_lsa_trans_names: adding domain '%s' sid %s to referenced list.\n", + dom_name, name )); - if (status == 0x0) - { - (*mapped_count)++; - } - else - { - snprintf(name, sizeof(name), "%08x", rid); - sid_name_use = SID_NAME_UNKNOWN; + dom_idx = init_dom_ref(ref, dom_name, &find_sid); + if(!status) { + slprintf(name, sizeof(name)-1, "unix.%08x", rid); + sid_name_use = SID_NAME_UNKNOWN; } - make_lsa_trans_name(&(trn->name [total]), - &(trn->uni_name[total]), - sid_name_use, name, dom_idx); + + DEBUG(10,("init_lsa_trans_names: added user '%s\\%s' to referenced list.\n", dom_name, name )); + + (*mapped_count)++; + + init_lsa_trans_name(&trn->name[total], &trn->uni_name[total], + sid_name_use, name, dom_idx); total++; } @@ -378,11 +353,12 @@ static void make_lsa_trans_names(DOM_R_REF *ref, } /*************************************************************************** -make_reply_lookup_sids + Init_reply_lookup_sids. ***************************************************************************/ -static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, - DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names, - uint32 mapped_count) + +static void init_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, + DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names, + uint32 mapped_count) { r_l->ptr_dom_ref = 1; r_l->dom_ref = ref; @@ -390,20 +366,16 @@ static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, r_l->mapped_count = mapped_count; if (mapped_count == 0) - { r_l->status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - } else - { r_l->status = 0x0; - } } /*************************************************************************** lsa_reply_lookup_sids ***************************************************************************/ -static void lsa_reply_lookup_sids(prs_struct *rdata, - DOM_SID2 *sid, int num_entries) + +static BOOL lsa_reply_lookup_sids(prs_struct *rdata, DOM_SID2 *sid, int num_entries) { LSA_R_LOOKUP_SIDS r_l; DOM_R_REF ref; @@ -415,18 +387,24 @@ static void lsa_reply_lookup_sids(prs_struct *rdata, ZERO_STRUCT(names); /* set up the LSA Lookup SIDs response */ - make_lsa_trans_names(&ref, &names, num_entries, sid, &mapped_count); - make_reply_lookup_sids(&r_l, &ref, &names, mapped_count); + init_lsa_trans_names(&ref, &names, num_entries, sid, &mapped_count); + init_reply_lookup_sids(&r_l, &ref, &names, mapped_count); /* store the response in the SMB stream */ - lsa_io_r_lookup_sids("", &r_l, rdata, 0); + if(!lsa_io_r_lookup_sids("", &r_l, rdata, 0)) { + DEBUG(0,("lsa_reply_lookup_sids: Failed to marshall LSA_R_LOOKUP_SIDS.\n")); + return False; + } + + return True; } /*************************************************************************** lsa_reply_lookup_names ***************************************************************************/ -static void lsa_reply_lookup_names(prs_struct *rdata, - UNISTR2 names[MAX_LOOKUP_SIDS], int num_entries) + +static BOOL lsa_reply_lookup_names(prs_struct *rdata, + UNISTR2 names[MAX_LOOKUP_SIDS], int num_entries) { LSA_R_LOOKUP_NAMES r_l; DOM_R_REF ref; @@ -435,20 +413,26 @@ static void lsa_reply_lookup_names(prs_struct *rdata, ZERO_STRUCT(r_l); ZERO_STRUCT(ref); - ZERO_STRUCT(rids); + ZERO_ARRAY(rids); /* set up the LSA Lookup RIDs response */ - make_lsa_rid2s(&ref, rids, num_entries, names, &mapped_count); - make_reply_lookup_names(&r_l, &ref, num_entries, rids, mapped_count); + init_lsa_rid2s(&ref, rids, num_entries, names, &mapped_count); + init_reply_lookup_names(&r_l, &ref, num_entries, rids, mapped_count); /* store the response in the SMB stream */ - lsa_io_r_lookup_names("", &r_l, rdata, 0); + if(!lsa_io_r_lookup_names("", &r_l, rdata, 0)) { + DEBUG(0,("lsa_reply_lookup_names: Failed to marshall LSA_R_LOOKUP_NAMES.\n")); + return False; + } + + return True; } /*************************************************************************** -api_lsa_open_policy + api_lsa_open_policy2 ***************************************************************************/ -static void api_lsa_open_policy2( rpcsrv_struct *p, prs_struct *data, + +static BOOL api_lsa_open_policy2( uint16 vuid, prs_struct *data, prs_struct *rdata ) { LSA_Q_OPEN_POL2 q_o; @@ -456,18 +440,24 @@ static void api_lsa_open_policy2( rpcsrv_struct *p, prs_struct *data, ZERO_STRUCT(q_o); /* grab the server, object attributes and desired access flag...*/ - lsa_io_q_open_pol2("", &q_o, data, 0); + if(!lsa_io_q_open_pol2("", &q_o, data, 0)) { + DEBUG(0,("api_lsa_open_policy2: unable to unmarshall LSA_Q_OPEN_POL2.\n")); + return False; + } /* lkclXXXX having decoded it, ignore all fields in the open policy! */ /* return a 20 byte policy handle */ - lsa_reply_open_policy2(rdata); + if(!lsa_reply_open_policy2(rdata)) + return False; + + return True; } /*************************************************************************** api_lsa_open_policy ***************************************************************************/ -static void api_lsa_open_policy( rpcsrv_struct *p, prs_struct *data, +static BOOL api_lsa_open_policy( uint16 vuid, prs_struct *data, prs_struct *rdata ) { LSA_Q_OPEN_POL q_o; @@ -475,18 +465,24 @@ static void api_lsa_open_policy( rpcsrv_struct *p, prs_struct *data, ZERO_STRUCT(q_o); /* grab the server, object attributes and desired access flag...*/ - lsa_io_q_open_pol("", &q_o, data, 0); + if(!lsa_io_q_open_pol("", &q_o, data, 0)) { + DEBUG(0,("api_lsa_open_policy: unable to unmarshall LSA_Q_OPEN_POL.\n")); + return False; + } /* lkclXXXX having decoded it, ignore all fields in the open policy! */ /* return a 20 byte policy handle */ - lsa_reply_open_policy(rdata); + if(!lsa_reply_open_policy(rdata)) + return False; + + return True; } /*************************************************************************** api_lsa_enum_trust_dom ***************************************************************************/ -static void api_lsa_enum_trust_dom( rpcsrv_struct *p, prs_struct *data, +static BOOL api_lsa_enum_trust_dom( uint16 vuid, prs_struct *data, prs_struct *rdata ) { LSA_Q_ENUM_TRUST_DOM q_e; @@ -498,12 +494,14 @@ static void api_lsa_enum_trust_dom( rpcsrv_struct *p, prs_struct *data, /* construct reply. return status is always 0x0 */ lsa_reply_enum_trust_dom(&q_e, rdata, 0, NULL, NULL); + + return True; } /*************************************************************************** api_lsa_query_info ***************************************************************************/ -static void api_lsa_query_info( rpcsrv_struct *p, prs_struct *data, +static BOOL api_lsa_query_info( uint16 vuid, prs_struct *data, prs_struct *rdata ) { LSA_Q_QUERY_INFO q_i; @@ -514,119 +512,118 @@ static void api_lsa_query_info( rpcsrv_struct *p, prs_struct *data, ZERO_STRUCT(q_i); /* grab the info class and policy handle */ - lsa_io_q_query("", &q_i, data, 0); - - switch (q_i.info_class) - { - case 0x03: - { - fstrcpy(name, global_myworkgroup); - sid = &global_member_sid; - break; - } - case 0x05: - { - fstrcpy(name, global_sam_name); - sid = &global_sam_sid; - break; - } - default: - { - DEBUG(5,("unknown info level in Lsa Query: %d\n", - q_i.info_class)); - break; - } + if(!lsa_io_q_query("", &q_i, data, 0)) { + DEBUG(0,("api_lsa_query_info: failed to unmarshall LSA_Q_QUERY_INFO.\n")); + return False; + } + + switch (q_i.info_class) { + case 0x03: + fstrcpy(name, global_myworkgroup); + sid = &global_sam_sid; + break; + case 0x05: + fstrcpy(name, global_myname); + sid = &global_sam_sid; + break; + default: + DEBUG(0,("api_lsa_query_info: unknown info level in Lsa Query: %d\n", q_i.info_class)); + break; } /* construct reply. return status is always 0x0 */ - lsa_reply_query_info(&q_i, rdata, name, sid); + if(!lsa_reply_query_info(&q_i, rdata, name, sid)) + return False; + + return True; } /*************************************************************************** -api_lsa_lookup_sids + api_lsa_lookup_sids ***************************************************************************/ -static void api_lsa_lookup_sids( rpcsrv_struct *p, prs_struct *data, - prs_struct *rdata ) + +static BOOL api_lsa_lookup_sids( uint16 vuid, prs_struct *data, prs_struct *rdata ) { LSA_Q_LOOKUP_SIDS q_l; ZERO_STRUCT(q_l); /* grab the info class and policy handle */ - lsa_io_q_lookup_sids("", &q_l, data, 0); + if(!lsa_io_q_lookup_sids("", &q_l, data, 0)) { + DEBUG(0,("api_lsa_lookup_sids: failed to unmarshall LSA_Q_LOOKUP_SIDS.\n")); + return False; + } /* construct reply. return status is always 0x0 */ - lsa_reply_lookup_sids(rdata, q_l.sids.sid, q_l.sids.num_entries); + if(!lsa_reply_lookup_sids(rdata, q_l.sids.sid, q_l.sids.num_entries)) + return False; + + return True; } /*************************************************************************** -api_lsa_lookup_names + api_lsa_lookup_names ***************************************************************************/ -static void api_lsa_lookup_names( rpcsrv_struct *p, prs_struct *data, - prs_struct *rdata ) + +static BOOL api_lsa_lookup_names( uint16 vuid, prs_struct *data, prs_struct *rdata ) { LSA_Q_LOOKUP_NAMES q_l; ZERO_STRUCT(q_l); /* grab the info class and policy handle */ - lsa_io_q_lookup_names("", &q_l, data, 0); + if(!lsa_io_q_lookup_names("", &q_l, data, 0)) { + DEBUG(0,("api_lsa_lookup_names: failed to unmarshall LSA_Q_LOOKUP_NAMES.\n")); + return False; + } SMB_ASSERT_ARRAY(q_l.uni_name, q_l.num_entries); - lsa_reply_lookup_names(rdata, q_l.uni_name, q_l.num_entries); + return lsa_reply_lookup_names(rdata, q_l.uni_name, q_l.num_entries); } /*************************************************************************** api_lsa_close ***************************************************************************/ -static void api_lsa_close( rpcsrv_struct *p, prs_struct *data, +static BOOL api_lsa_close( uint16 vuid, prs_struct *data, prs_struct *rdata) { LSA_R_CLOSE r_c; - LSA_Q_CLOSE q_c; - - lsa_io_q_close("", &q_c, data, 0); ZERO_STRUCT(r_c); - r_c.status = 0x0; - - /* find the connection policy handle. */ - if (r_c.status == 0x0 && (find_policy_by_hnd(&(q_c.pol)) == -1)) - { - r_c.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - if (r_c.status == 0x0) - { - close_policy_hnd(&(q_c.pol)); + /* store the response in the SMB stream */ + if (!lsa_io_r_close("", &r_c, rdata, 0)) { + DEBUG(0,("api_lsa_close: lsa_io_r_close failed.\n")); + return False; } - /* store the response in the SMB stream */ - lsa_io_r_close("", &r_c, rdata, 0); + return True; } /*************************************************************************** api_lsa_open_secret ***************************************************************************/ -static void api_lsa_open_secret( rpcsrv_struct *p, prs_struct *data, +static BOOL api_lsa_open_secret( uint16 vuid, prs_struct *data, prs_struct *rdata) { /* XXXX this is NOT good */ - char *q = mem_data(&(rdata->data), rdata->offset); - - SIVAL(q, 0, 0); - q += 4; - SIVAL(q, 0, 0); - q += 4; - SIVAL(q, 0, 0); - q += 4; - SIVAL(q, 0, 0); - q += 4; - SIVAL(q, 0, 0); - q += 4; - SIVAL(q, 0, 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND); - q += 4; - - rdata->offset += 24; + size_t i; + uint32 dummy = 0; + + for(i =0; i < 4; i++) { + if(!prs_uint32("api_lsa_close", rdata, 1, &dummy)) { + DEBUG(0,("api_lsa_open_secret: prs_uint32 %d failed.\n", + (int)i )); + return False; + } + } + + dummy = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + if(!prs_uint32("api_lsa_close", rdata, 1, &dummy)) { + DEBUG(0,("api_lsa_open_secret: prs_uint32 status failed.\n")); + return False; + } + + return True; } /*************************************************************************** @@ -648,7 +645,7 @@ static struct api_struct api_lsa_cmds[] = /*************************************************************************** api_ntLsarpcTNP ***************************************************************************/ -BOOL api_ntlsa_rpc(rpcsrv_struct *p, prs_struct *data) +BOOL api_ntlsa_rpc(pipes_struct *p, prs_struct *data) { return api_rpcTNP(p, "api_ntlsa_rpc", api_lsa_cmds, data); } diff --git a/source3/rpc_server/srv_lsa_hnd.c b/source3/rpc_server/srv_lsa_hnd.c index b895fb31c0..24aec701f0 100644 --- a/source3/rpc_server/srv_lsa_hnd.c +++ b/source3/rpc_server/srv_lsa_hnd.c @@ -31,11 +31,6 @@ extern int DEBUGLEVEL; #define MAX_OPEN_POLS 64 #endif -#define POL_NO_INFO 0 -#define POL_REG_INFO 1 -#define POL_SAMR_INFO 2 -#define POL_CLI_INFO 3 - struct reg_info { /* for use by \PIPE\winreg */ @@ -50,27 +45,17 @@ struct samr_info uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */ }; -struct con_info -{ - struct cli_connection *con; - void (*free)(struct cli_connection*); -}; - static struct policy { struct policy *next, *prev; int pnum; BOOL open; POLICY_HND pol_hnd; - int type; union { - struct samr_info *samr; - struct reg_info *reg; - struct con_info *con; - + struct samr_info samr; + struct reg_info reg; } dev; - } *Policy; static struct bitmap *bmap; @@ -100,17 +85,18 @@ static void create_pol_hnd(POLICY_HND *hnd) /**************************************************************************** initialise policy handle states... ****************************************************************************/ -BOOL init_policy_hnd(int num_pol_hnds) +void init_lsa_policy_hnd(void) { - bmap = bitmap_allocate(num_pol_hnds); - - return bmap != NULL; + bmap = bitmap_allocate(MAX_OPEN_POLS); + if (!bmap) { + exit_server("out of memory in init_lsa_policy_hnd\n"); + } } /**************************************************************************** find first available policy slot. creates a policy handle for you. ****************************************************************************/ -BOOL register_policy_hnd(POLICY_HND *hnd) +BOOL open_lsa_policy_hnd(POLICY_HND *hnd) { int i; struct policy *p; @@ -132,8 +118,8 @@ BOOL register_policy_hnd(POLICY_HND *hnd) p->open = True; p->pnum = i; - p->type = POL_NO_INFO; + create_pol_hnd(hnd); memcpy(&p->pol_hnd, hnd, sizeof(*hnd)); bitmap_set(bmap, i); @@ -146,33 +132,23 @@ BOOL register_policy_hnd(POLICY_HND *hnd) return True; } -/**************************************************************************** - find first available policy slot. creates a policy handle for you. -****************************************************************************/ -BOOL open_policy_hnd(POLICY_HND *hnd) -{ - create_pol_hnd(hnd); - return register_policy_hnd(hnd); -} - /**************************************************************************** find policy by handle ****************************************************************************/ -static struct policy *find_policy(const POLICY_HND *hnd) +static struct policy *find_lsa_policy(POLICY_HND *hnd) { struct policy *p; for (p=Policy;p;p=p->next) { if (memcmp(&p->pol_hnd, hnd, sizeof(*hnd)) == 0) { DEBUG(4,("Found policy hnd[%x] ", p->pnum)); - dump_data(4, (const char *)hnd->data, - sizeof(hnd->data)); + dump_data(4, (char *)hnd->data, sizeof(hnd->data)); return p; } } DEBUG(4,("Policy not found: ")); - dump_data(4, (const char *)hnd->data, sizeof(hnd->data)); + dump_data(4, (char *)hnd->data, sizeof(hnd->data)); return NULL; } @@ -180,9 +156,9 @@ static struct policy *find_policy(const POLICY_HND *hnd) /**************************************************************************** find policy index by handle ****************************************************************************/ -int find_policy_by_hnd(const POLICY_HND *hnd) +int find_lsa_policy_by_hnd(POLICY_HND *hnd) { - struct policy *p = find_policy(hnd); + struct policy *p = find_lsa_policy(hnd); return p?p->pnum:-1; } @@ -190,24 +166,15 @@ int find_policy_by_hnd(const POLICY_HND *hnd) /**************************************************************************** set samr rid ****************************************************************************/ -BOOL set_policy_samr_rid(POLICY_HND *hnd, uint32 rid) +BOOL set_lsa_policy_samr_rid(POLICY_HND *hnd, uint32 rid) { - struct policy *p = find_policy(hnd); + struct policy *p = find_lsa_policy(hnd); - if (p && p->open) - { + if (p && p->open) { DEBUG(3,("Setting policy device rid=%x pnum=%x\n", rid, p->pnum)); - if (p->dev.samr == NULL) - { - p->dev.samr = (struct samr_info*)malloc(sizeof(*p->dev.samr)); - } - if (p->dev.samr == NULL) - { - return False; - } - p->dev.samr->rid = rid; + p->dev.samr.rid = rid; return True; } @@ -219,25 +186,15 @@ BOOL set_policy_samr_rid(POLICY_HND *hnd, uint32 rid) /**************************************************************************** set samr pol status. absolutely no idea what this is. ****************************************************************************/ -BOOL set_policy_samr_pol_status(POLICY_HND *hnd, uint32 pol_status) +BOOL set_lsa_policy_samr_pol_status(POLICY_HND *hnd, uint32 pol_status) { - struct policy *p = find_policy(hnd); + struct policy *p = find_lsa_policy(hnd); - if (p && p->open) - { + if (p && p->open) { DEBUG(3,("Setting policy status=%x pnum=%x\n", pol_status, p->pnum)); - if (p->dev.samr == NULL) - { - p->type = POL_SAMR_INFO; - p->dev.samr = (struct samr_info*)malloc(sizeof(*p->dev.samr)); - } - if (p->dev.samr == NULL) - { - return False; - } - p->dev.samr->status = pol_status; + p->dev.samr.status = pol_status; return True; } @@ -249,25 +206,16 @@ BOOL set_policy_samr_pol_status(POLICY_HND *hnd, uint32 pol_status) /**************************************************************************** set samr sid ****************************************************************************/ -BOOL set_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid) +BOOL set_lsa_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid) { - pstring sidstr; - struct policy *p = find_policy(hnd); + fstring sidstr; + struct policy *p = find_lsa_policy(hnd); if (p && p->open) { DEBUG(3,("Setting policy sid=%s pnum=%x\n", sid_to_string(sidstr, sid), p->pnum)); - if (p->dev.samr == NULL) - { - p->type = POL_SAMR_INFO; - p->dev.samr = (struct samr_info*)malloc(sizeof(*p->dev.samr)); - } - if (p->dev.samr == NULL) - { - return False; - } - memcpy(&p->dev.samr->sid, sid, sizeof(*sid)); + memcpy(&p->dev.samr.sid, sid, sizeof(*sid)); return True; } @@ -279,14 +227,14 @@ BOOL set_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid) /**************************************************************************** get samr sid ****************************************************************************/ -BOOL get_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid) +BOOL get_lsa_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid) { - struct policy *p = find_policy(hnd); + struct policy *p = find_lsa_policy(hnd); if (p != NULL && p->open) { - pstring sidstr; - memcpy(sid, &p->dev.samr->sid, sizeof(*sid)); + fstring sidstr; + memcpy(sid, &p->dev.samr.sid, sizeof(*sid)); DEBUG(3,("Getting policy sid=%s pnum=%x\n", sid_to_string(sidstr, sid), p->pnum)); @@ -300,12 +248,12 @@ BOOL get_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid) /**************************************************************************** get samr rid ****************************************************************************/ -uint32 get_policy_samr_rid(POLICY_HND *hnd) +uint32 get_lsa_policy_samr_rid(POLICY_HND *hnd) { - struct policy *p = find_policy(hnd); + struct policy *p = find_lsa_policy(hnd); if (p && p->open) { - uint32 rid = p->dev.samr->rid; + uint32 rid = p->dev.samr.rid; DEBUG(3,("Getting policy device rid=%x pnum=%x\n", rid, p->pnum)); @@ -319,116 +267,30 @@ uint32 get_policy_samr_rid(POLICY_HND *hnd) /**************************************************************************** set reg name ****************************************************************************/ -BOOL set_policy_reg_name(POLICY_HND *hnd, fstring name) -{ - struct policy *p = find_policy(hnd); - - if (p && p->open) - { - DEBUG(3,("Getting policy pnum=%x\n", - p->pnum)); - - if (p->dev.reg == NULL) - { - p->type = POL_REG_INFO; - p->dev.reg = (struct reg_info*)malloc(sizeof(*p->dev.reg)); - } - if (p->dev.reg == NULL) - { - return False; - } - fstrcpy(p->dev.reg->name, name); - return True; - } - - DEBUG(3,("Error setting policy name=%s\n", name)); - return False; -} - -/**************************************************************************** - set reg name -****************************************************************************/ -BOOL get_policy_reg_name(POLICY_HND *hnd, fstring name) +BOOL set_lsa_policy_reg_name(POLICY_HND *hnd, fstring name) { - struct policy *p = find_policy(hnd); + struct policy *p = find_lsa_policy(hnd); - if (p && p->open) - { + if (p && p->open) { DEBUG(3,("Setting policy pnum=%x name=%s\n", p->pnum, name)); - fstrcpy(name, p->dev.reg->name); - DEBUG(5,("getting policy reg name=%s\n", name)); - return True; - } - - DEBUG(3,("Error getting policy reg name\n")); - return False; -} - -/**************************************************************************** - set con state -****************************************************************************/ -BOOL set_policy_con(POLICY_HND *hnd, struct cli_connection *con, - void (*free_fn)(struct cli_connection *)) -{ - struct policy *p = find_policy(hnd); - - if (p && p->open) - { - DEBUG(3,("Setting policy con state pnum=%x\n", p->pnum)); - - if (p->dev.con == NULL) - { - p->type = POL_CLI_INFO; - p->dev.con = (struct con_info*)malloc(sizeof(*p->dev.con)); - } - if (p->dev.con == NULL) - { - return False; - } - p->dev.con->con = con; - p->dev.con->free = free_fn; + fstrcpy(p->dev.reg.name, name); return True; } - DEBUG(3,("Error setting policy con state\n")); - - return False; -} - -/**************************************************************************** - get con state -****************************************************************************/ -BOOL get_policy_con(const POLICY_HND *hnd, struct cli_connection **con) -{ - struct policy *p = find_policy(hnd); - - if (p != NULL && p->open) - { - DEBUG(3,("Getting con state pnum=%x\n", p->pnum)); - - if (con != NULL) - { - (*con ) = p->dev.con->con; - } - - return True; - } - - DEBUG(3,("Error getting policy\n")); + DEBUG(3,("Error setting policy name=%s\n", name)); return False; } /**************************************************************************** close an lsa policy ****************************************************************************/ -BOOL close_policy_hnd(POLICY_HND *hnd) +BOOL close_lsa_policy_hnd(POLICY_HND *hnd) { - struct policy *p = find_policy(hnd); + struct policy *p = find_lsa_policy(hnd); - if (!p) - { + if (!p) { DEBUG(3,("Error closing policy\n")); return False; } @@ -440,33 +302,8 @@ BOOL close_policy_hnd(POLICY_HND *hnd) bitmap_clear(bmap, p->pnum); ZERO_STRUCTP(p); - ZERO_STRUCTP(hnd); - - switch (p->type) - { - case POL_REG_INFO: - { - free(p->dev.reg); - break; - } - case POL_SAMR_INFO: - { - free(p->dev.samr); - break; - } - case POL_CLI_INFO: - { - if (p->dev.con->free != NULL) - { - p->dev.con->free(p->dev.con->con); - } - free(p->dev.con); - break; - } - } free(p); return True; } - diff --git a/source3/rpc_server/srv_netlog.c b/source3/rpc_server/srv_netlog.c index 9721b3bf00..c0233d80c6 100644 --- a/source3/rpc_server/srv_netlog.c +++ b/source3/rpc_server/srv_netlog.c @@ -1,3 +1,4 @@ + /* * Unix SMB/Netbios implementation. * Version 1.9. @@ -28,17 +29,19 @@ extern int DEBUGLEVEL; +extern BOOL sam_logon_in_ssb; +extern pstring samlogon_user; extern pstring global_myname; extern DOM_SID global_sam_sid; -extern fstring global_sam_name; /************************************************************************* - make_net_r_req_chal: + init_net_r_req_chal: *************************************************************************/ -static void make_net_r_req_chal(NET_R_REQ_CHAL *r_c, + +static void init_net_r_req_chal(NET_R_REQ_CHAL *r_c, DOM_CHAL *srv_chal, int status) { - DEBUG(6,("make_net_r_req_chal: %d\n", __LINE__)); + DEBUG(6,("init_net_r_req_chal: %d\n", __LINE__)); memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); r_c->status = status; } @@ -46,7 +49,8 @@ static void make_net_r_req_chal(NET_R_REQ_CHAL *r_c, /************************************************************************* net_reply_req_chal: *************************************************************************/ -static void net_reply_req_chal(NET_Q_REQ_CHAL *q_c, prs_struct *rdata, + +static BOOL net_reply_req_chal(NET_Q_REQ_CHAL *q_c, prs_struct *rdata, DOM_CHAL *srv_chal, uint32 srv_time) { NET_R_REQ_CHAL r_c; @@ -54,19 +58,24 @@ static void net_reply_req_chal(NET_Q_REQ_CHAL *q_c, prs_struct *rdata, DEBUG(6,("net_reply_req_chal: %d\n", __LINE__)); /* set up the LSA REQUEST CHALLENGE response */ - make_net_r_req_chal(&r_c, srv_chal, srv_time); + init_net_r_req_chal(&r_c, srv_chal, srv_time); /* store the response in the SMB stream */ - net_io_r_req_chal("", &r_c, rdata, 0); + if(!net_io_r_req_chal("", &r_c, rdata, 0)) { + DEBUG(0,("net_reply_req_chal: Failed to marshall NET_R_REQ_CHAL.\n")); + return False; + } DEBUG(6,("net_reply_req_chal: %d\n", __LINE__)); + return True; } /************************************************************************* net_reply_logon_ctrl2: *************************************************************************/ -static void net_reply_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, prs_struct *rdata, + +static BOOL net_reply_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, prs_struct *rdata, uint32 flags, uint32 pdc_status, uint32 logon_attempts, uint32 tc_status, char *trust_domain_name) { @@ -75,80 +84,63 @@ static void net_reply_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, prs_struct *rdata, DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__)); /* set up the Logon Control2 response */ - make_r_logon_ctrl2(&r_l, q_l->query_level, + init_r_logon_ctrl2(&r_l, q_l->query_level, flags, pdc_status, logon_attempts, tc_status, trust_domain_name); /* store the response in the SMB stream */ - net_io_r_logon_ctrl2("", &r_l, rdata, 0); + if(!net_io_r_logon_ctrl2("", &r_l, rdata, 0)) { + DEBUG(0,("net_reply_logon_ctrl2: Failed to marshall NET_R_LOGON_CTRL2.\n")); + return False; + } DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__)); + return True; } /************************************************************************* net_reply_trust_dom_list: *************************************************************************/ -static void net_reply_trust_dom_list(NET_Q_TRUST_DOM_LIST *q_t, prs_struct *rdata, - uint32 num_trust_domains, char **trust_domain_name) + +static BOOL net_reply_trust_dom_list(NET_Q_TRUST_DOM_LIST *q_t, prs_struct *rdata, + uint32 num_trust_domains, char *trust_domain_name) { NET_R_TRUST_DOM_LIST r_t; DEBUG(6,("net_reply_trust_dom_list: %d\n", __LINE__)); /* set up the Trusted Domain List response */ - make_r_trust_dom(&r_t, num_trust_domains, trust_domain_name); + init_r_trust_dom(&r_t, num_trust_domains, trust_domain_name); /* store the response in the SMB stream */ - net_io_r_trust_dom("", &r_t, rdata, 0); + if(!net_io_r_trust_dom("", &r_t, rdata, 0)) { + DEBUG(0,("net_reply_trust_dom_list: Failed to marshall NET_R_TRUST_DOM_LIST.\n")); + return False; + } - DEBUG(6,("net_reply_trust_dom_list: %d\n", __LINE__)); + DEBUG(6,("net_reply_trust_dom_listlogon_ctrl2: %d\n", __LINE__)); + return True; } - /************************************************************************* - make_net_r_auth: + init_net_r_auth_2: *************************************************************************/ -static void make_net_r_auth(NET_R_AUTH *r_a, - DOM_CHAL *resp_cred, int status) -{ - memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data)); - r_a->status = status; -} -/************************************************************************* - net_reply_auth: - *************************************************************************/ -static void net_reply_auth(NET_Q_AUTH *q_a, prs_struct *rdata, - DOM_CHAL *resp_cred, int status) -{ - NET_R_AUTH r_a; - - /* set up the LSA AUTH 2 response */ - - make_net_r_auth(&r_a, resp_cred, status); - - /* store the response in the SMB stream */ - net_io_r_auth("", &r_a, rdata, 0); - -} - -/************************************************************************* - make_net_r_auth_2: - *************************************************************************/ -static void make_net_r_auth_2(NET_R_AUTH_2 *r_a, +static void init_net_r_auth_2(NET_R_AUTH_2 *r_a, DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status) { - memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data)); - memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs)); + memcpy(r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data)); + memcpy(&r_a->srv_flgs, flgs, sizeof(r_a->srv_flgs)); r_a->status = status; } -/************************************************************************* +/************************************************************************ net_reply_auth_2: *************************************************************************/ -static void net_reply_auth_2(NET_Q_AUTH_2 *q_a, prs_struct *rdata, + +static BOOL net_reply_auth_2(NET_Q_AUTH_2 *q_a, prs_struct *rdata, DOM_CHAL *resp_cred, int status) { NET_R_AUTH_2 r_a; @@ -158,31 +150,37 @@ static void net_reply_auth_2(NET_Q_AUTH_2 *q_a, prs_struct *rdata, /* set up the LSA AUTH 2 response */ - make_net_r_auth_2(&r_a, resp_cred, &srv_flgs, status); + init_net_r_auth_2(&r_a, resp_cred, &srv_flgs, status); /* store the response in the SMB stream */ - net_io_r_auth_2("", &r_a, rdata, 0); + if(!net_io_r_auth_2("", &r_a, rdata, 0)) { + DEBUG(0,("net_reply_auth_2: Failed to marshall NET_R_AUTH_2.\n")); + return False; + } + return True; } /*********************************************************************************** - make_net_r_srv_pwset: + init_net_r_srv_pwset: ***********************************************************************************/ -static void make_net_r_srv_pwset(NET_R_SRV_PWSET *r_s, + +static void init_net_r_srv_pwset(NET_R_SRV_PWSET *r_s, DOM_CRED *srv_cred, int status) { - DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__)); + DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__)); - memcpy(&(r_s->srv_cred), srv_cred, sizeof(r_s->srv_cred)); + memcpy(&r_s->srv_cred, srv_cred, sizeof(r_s->srv_cred)); r_s->status = status; - DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__)); + DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__)); } /************************************************************************* net_reply_srv_pwset: *************************************************************************/ -static void net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata, + +static BOOL net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata, DOM_CRED *srv_cred, int status) { NET_R_SRV_PWSET r_s; @@ -190,19 +188,24 @@ static void net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata, DEBUG(5,("net_srv_pwset: %d\n", __LINE__)); /* set up the LSA Server Password Set response */ - make_net_r_srv_pwset(&r_s, srv_cred, status); + init_net_r_srv_pwset(&r_s, srv_cred, status); /* store the response in the SMB stream */ - net_io_r_srv_pwset("", &r_s, rdata, 0); + if(!net_io_r_srv_pwset("", &r_s, rdata, 0)) { + DEBUG(0,("net_reply_srv_pwset: Failed to marshall NET_R_SRV_PWSET.\n")); + return False; + } DEBUG(5,("net_srv_pwset: %d\n", __LINE__)); + return True; } /************************************************************************* net_reply_sam_logon: *************************************************************************/ -static void net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata, + +static BOOL net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata, DOM_CRED *srv_cred, NET_USER_INFO_3 *user_info, uint32 status) { @@ -210,32 +213,33 @@ static void net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata, /* XXXX maybe we want to say 'no', reject the client's credentials */ r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); + memcpy(&r_s.srv_creds, srv_cred, sizeof(r_s.srv_creds)); /* store the user information, if there is any. */ r_s.user = user_info; if (status == 0x0 && user_info != NULL && user_info->ptr_user_info != 0) - { r_s.switch_value = 3; /* indicates type of validation user info */ - } else - { r_s.switch_value = 0; /* indicates no info */ - } r_s.status = status; r_s.auth_resp = 1; /* authoritative response */ /* store the response in the SMB stream */ - net_io_r_sam_logon("", &r_s, rdata, 0); + if(!net_io_r_sam_logon("", &r_s, rdata, 0)) { + DEBUG(0,("net_reply_sam_logon: Failed to marshall NET_R_SAM_LOGON.\n")); + return False; + } + return True; } /************************************************************************* net_reply_sam_logoff: *************************************************************************/ -static void net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata, + +static BOOL net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata, DOM_CRED *srv_cred, uint32 status) { @@ -243,63 +247,23 @@ static void net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata, /* XXXX maybe we want to say 'no', reject the client's credentials */ r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); + memcpy(&r_s.srv_creds, srv_cred, sizeof(r_s.srv_creds)); r_s.status = status; /* store the response in the SMB stream */ - net_io_r_sam_logoff("", &r_s, rdata, 0); - -} - -/************************************************************************* - net_reply_sam_sync: - *************************************************************************/ -static void net_reply_sam_sync(NET_Q_SAM_SYNC *q_s, prs_struct *rdata, - uint8 sess_key[16], - DOM_CRED *srv_creds, uint32 status) -{ - NET_R_SAM_SYNC r_s; - int i = 0; - struct sam_passwd *pwd; - void *vp; - - memcpy(&(r_s.srv_creds), srv_creds, sizeof(r_s.srv_creds)); - r_s.sync_context = 1; - r_s.ptr_deltas = 0; - - if ((status == 0x0) && ((vp = startsmbpwent(False)) != NULL)) - { - /* Give the poor BDC some accounts */ - - while (((pwd = getsam21pwent(vp)) != NULL) && (i < MAX_SAM_DELTAS)) - { - make_sam_delta_hdr(&r_s.hdr_deltas[i], 5, pwd->user_rid); - make_sam_account_info(&r_s.deltas[i].account_info, - pwd->nt_name, pwd->full_name, pwd->user_rid, - pwd->group_rid, pwd->home_dir, pwd->dir_drive, - pwd->logon_script, pwd->acct_desc, - pwd->acct_ctrl, pwd->profile_path); - - i++; - } - - endsmbpwent(vp); - - r_s.ptr_deltas = r_s.ptr_deltas2 = 1; - r_s.num_deltas = r_s.num_deltas2 = i; + if(!net_io_r_sam_logoff("", &r_s, rdata, 0)) { + DEBUG(0,("net_reply_sam_logoff: Failed to marshall NET_R_SAM_LOGOFF.\n")); + return False; } - r_s.status = status; - - /* store the response in the SMB stream */ - net_io_r_sam_sync("", sess_key, &r_s, rdata, 0); - + return True; } /****************************************************************** gets a machine password entry. checks access rights of the host. ******************************************************************/ + static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct) { struct smb_passwd *smb_pass; @@ -334,13 +298,6 @@ static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct) return True; } - if (strequal(mach_name, global_myname)) - { - DEBUG(0,("get_md4pw: *** LOOPBACK DETECTED - USING NULL KEY ***\n")); - memset(md4pw, 0, 16); - return True; - } - DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct)); return False; } @@ -348,9 +305,8 @@ static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct) /************************************************************************* api_net_req_chal: *************************************************************************/ -static void api_net_req_chal( rpcsrv_struct *p, - prs_struct *data, - prs_struct *rdata) + +static BOOL api_net_req_chal( uint16 vuid, prs_struct *data, prs_struct *rdata) { NET_Q_REQ_CHAL q_r; uint32 status = 0x0; @@ -358,93 +314,60 @@ static void api_net_req_chal( rpcsrv_struct *p, fstring mach_acct; fstring mach_name; - DEBUG(5,("api_net_req_chal(%d)\n", __LINE__)); + user_struct *vuser; + + DEBUG(5,("api_net_req_chal(%d): vuid %d\n", __LINE__, (int)vuid)); + + if ((vuser = get_valid_user_struct(vuid)) == NULL) + return False; /* grab the challenge... */ - net_io_q_req_chal("", &q_r, data, 0); + if(!net_io_q_req_chal("", &q_r, data, 0)) { + DEBUG(0,("api_net_req_chal: Failed to unmarshall NET_Q_REQ_CHAL.\n")); + return False; + } - unistr2_to_ascii(mach_acct, &q_r.uni_logon_clnt, sizeof(mach_acct)-1); + fstrcpy(mach_acct, dos_unistrn2(q_r.uni_logon_clnt.buffer, + q_r.uni_logon_clnt.uni_str_len)); fstrcpy(mach_name, mach_acct); strlower(mach_name); fstrcat(mach_acct, "$"); - if (get_md4pw((char *)p->dc.md4pw, mach_name, mach_acct)) - { + if (get_md4pw((char *)vuser->dc.md4pw, mach_name, mach_acct)) { /* copy the client credentials */ - memcpy(p->dc.clnt_chal.data , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); - memcpy(p->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); + memcpy(vuser->dc.clnt_chal.data , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); + memcpy(vuser->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); /* create a server challenge for the client */ /* Set these to random values. */ - generate_random_buffer(p->dc.srv_chal.data, 8, False); + generate_random_buffer(vuser->dc.srv_chal.data, 8, False); - memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8); + memcpy(vuser->dc.srv_cred.challenge.data, vuser->dc.srv_chal.data, 8); - bzero(p->dc.sess_key, sizeof(p->dc.sess_key)); + memset((char *)vuser->dc.sess_key, '\0', sizeof(vuser->dc.sess_key)); /* from client / server challenges and md4 password, generate sess key */ - cred_session_key(&(p->dc.clnt_chal), &(p->dc.srv_chal), - (char *)p->dc.md4pw, p->dc.sess_key); - } - else - { + cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal), + (char *)vuser->dc.md4pw, vuser->dc.sess_key); + } else { /* lkclXXXX take a guess at a good error message to return :-) */ status = 0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } /* construct reply. */ - net_reply_req_chal(&q_r, rdata, - &(p->dc.srv_chal), status); - -} - -/************************************************************************* - api_net_auth: - *************************************************************************/ -static void api_net_auth( rpcsrv_struct *p, - prs_struct *data, - prs_struct *rdata) -{ - NET_Q_AUTH q_a; - uint32 status = 0x0; - - DOM_CHAL srv_cred; - UTIME srv_time; - - srv_time.time = 0; - - /* grab the challenge... */ - net_io_q_auth("", &q_a, data, 0); - - /* check that the client credentials are valid */ - if (cred_assert(&(q_a.clnt_chal), p->dc.sess_key, - &(p->dc.clnt_cred.challenge), srv_time)) - { - - /* create server challenge for inclusion in the reply */ - cred_create(p->dc.sess_key, &(p->dc.srv_cred.challenge), srv_time, &srv_cred); - - /* copy the received client credentials for use next time */ - memcpy(p->dc.clnt_cred.challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data)); - memcpy(p->dc.srv_cred .challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data)); - } - else - { - status = NT_STATUS_ACCESS_DENIED | 0xC0000000; - } + if(!net_reply_req_chal(&q_r, rdata, &vuser->dc.srv_chal, status)) + return False; - /* construct reply. */ - net_reply_auth(&q_a, rdata, &srv_cred, status); + return True; } /************************************************************************* api_net_auth_2: *************************************************************************/ -static void api_net_auth_2( rpcsrv_struct *p, - prs_struct *data, - prs_struct *rdata) + +static BOOL api_net_auth_2( uint16 vuid, prs_struct *data, prs_struct *rdata) { NET_Q_AUTH_2 q_a; uint32 status = 0x0; @@ -452,38 +375,46 @@ static void api_net_auth_2( rpcsrv_struct *p, DOM_CHAL srv_cred; UTIME srv_time; + user_struct *vuser; + + if ((vuser = get_valid_user_struct(vuid)) == NULL) + return False; + srv_time.time = 0; /* grab the challenge... */ - net_io_q_auth_2("", &q_a, data, 0); + if(!net_io_q_auth_2("", &q_a, data, 0)) { + DEBUG(0,("api_net_auth_2: Failed to unmarshall NET_Q_AUTH_2.\n")); + return False; + } /* check that the client credentials are valid */ - if (cred_assert(&(q_a.clnt_chal), p->dc.sess_key, - &(p->dc.clnt_cred.challenge), srv_time)) - { + if (cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, + &(vuser->dc.clnt_cred.challenge), srv_time)) { /* create server challenge for inclusion in the reply */ - cred_create(p->dc.sess_key, &(p->dc.srv_cred.challenge), srv_time, &srv_cred); + cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred.challenge), srv_time, &srv_cred); /* copy the received client credentials for use next time */ - memcpy(p->dc.clnt_cred.challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data)); - memcpy(p->dc.srv_cred .challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data)); - } - else - { + memcpy(vuser->dc.clnt_cred.challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data)); + memcpy(vuser->dc.srv_cred .challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data)); + } else { status = NT_STATUS_ACCESS_DENIED | 0xC0000000; } /* construct reply. */ - net_reply_auth_2(&q_a, rdata, &srv_cred, status); + if(!net_reply_auth_2(&q_a, rdata, &srv_cred, status)) + return False; + + return True; } + /************************************************************************* api_net_srv_pwset: *************************************************************************/ -static void api_net_srv_pwset( rpcsrv_struct *p, - prs_struct *data, - prs_struct *rdata) + +static BOOL api_net_srv_pwset( uint16 vuid, prs_struct *data, prs_struct *rdata) { NET_Q_SRV_PWSET q_a; uint32 status = NT_STATUS_WRONG_PASSWORD|0xC0000000; @@ -491,20 +422,27 @@ static void api_net_srv_pwset( rpcsrv_struct *p, pstring mach_acct; struct smb_passwd *smb_pass; BOOL ret; + user_struct *vuser; + + if ((vuser = get_valid_user_struct(vuid)) == NULL) + return False; /* grab the challenge and encrypted password ... */ - net_io_q_srv_pwset("", &q_a, data, 0); + if(!net_io_q_srv_pwset("", &q_a, data, 0)) { + DEBUG(0,("api_net_srv_pwset: Failed to unmarshall NET_Q_SRV_PWSET.\n")); + return False; + } /* checks and updates credentials. creates reply credentials */ - if (deal_with_creds(p->dc.sess_key, &(p->dc.clnt_cred), + if (deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), &(q_a.clnt_id.cred), &srv_cred)) { - memcpy(&(p->dc.srv_cred), &(p->dc.clnt_cred), sizeof(p->dc.clnt_cred)); + memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred)); DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__)); - unistr2_to_ascii(mach_acct, &q_a.clnt_id.login.uni_acct_name, - sizeof(mach_acct)-1); + pstrcpy(mach_acct, dos_unistrn2(q_a.clnt_id.login.uni_acct_name.buffer, + q_a.clnt_id.login.uni_acct_name.uni_str_len)); DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct)); @@ -512,19 +450,16 @@ static void api_net_srv_pwset( rpcsrv_struct *p, smb_pass = getsmbpwnam(mach_acct); unbecome_root(True); - if (smb_pass != NULL) - { + if (smb_pass != NULL) { unsigned char pwd[16]; int i; DEBUG(100,("Server password set : new given value was :\n")); for(i = 0; i < 16; i++) - { DEBUG(100,("%02X ", q_a.pwd[i])); - } DEBUG(100,("\n")); - cred_hash3( pwd, q_a.pwd, p->dc.sess_key, 0); + cred_hash3( pwd, q_a.pwd, vuser->dc.sess_key, 0); /* lies! nt and lm passwords are _not_ the same: don't care */ smb_pass->smb_passwd = pwd; @@ -535,8 +470,7 @@ static void api_net_srv_pwset( rpcsrv_struct *p, ret = mod_smbpwd_entry(smb_pass,False); unbecome_root(True); - if (ret) - { + if (ret) { /* hooray! */ status = 0x0; } @@ -544,83 +478,63 @@ static void api_net_srv_pwset( rpcsrv_struct *p, DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__)); - } - else - { + } else { /* lkclXXXX take a guess at a sensible error code to return... */ status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT; } /* Construct reply. */ - net_reply_srv_pwset(&q_a, rdata, &srv_cred, status); + if(!net_reply_srv_pwset(&q_a, rdata, &srv_cred, status)) + return False; + + return True; } /************************************************************************* api_net_sam_logoff: *************************************************************************/ -static void api_net_sam_logoff( rpcsrv_struct *p, - prs_struct *data, - prs_struct *rdata) + +static BOOL api_net_sam_logoff( uint16 vuid, prs_struct *data, prs_struct *rdata) { NET_Q_SAM_LOGOFF q_l; NET_ID_INFO_CTR ctr; DOM_CRED srv_cred; + user_struct *vuser; + + if ((vuser = get_valid_user_struct(vuid)) == NULL) + return False; + /* the DOM_ID_INFO_1 structure is a bit big. plus we might want to dynamically allocate it inside net_io_q_sam_logon, at some point */ q_l.sam_id.ctr = &ctr; /* grab the challenge... */ - net_io_q_sam_logoff("", &q_l, data, 0); + if(!net_io_q_sam_logoff("", &q_l, data, 0)) { + DEBUG(0,("api_net_sam_logoff: Failed to unmarshall NET_Q_SAM_LOGOFF.\n")); + return False; + } /* checks and updates credentials. creates reply credentials */ - deal_with_creds(p->dc.sess_key, &(p->dc.clnt_cred), - &(q_l.sam_id.client.cred), &srv_cred); - memcpy(&(p->dc.srv_cred), &(p->dc.clnt_cred), sizeof(p->dc.clnt_cred)); + deal_with_creds(vuser->dc.sess_key, &vuser->dc.clnt_cred, + &q_l.sam_id.client.cred, &srv_cred); + memcpy(&vuser->dc.srv_cred, &vuser->dc.clnt_cred, sizeof(vuser->dc.clnt_cred)); /* construct reply. always indicate success */ - net_reply_sam_logoff(&q_l, rdata, &srv_cred, 0x0); -} - -/************************************************************************* - api_net_sam_sync: - *************************************************************************/ -static void api_net_sam_sync( rpcsrv_struct *p, - prs_struct *data, - prs_struct *rdata) -{ - NET_Q_SAM_SYNC q_s; - DOM_CRED srv_creds; - uint32 status = 0x0; - - /* grab the challenge... */ - net_io_q_sam_sync("", &q_s, data, 0); - - /* checks and updates credentials. creates reply credentials */ - if (deal_with_creds(p->dc.sess_key, &(p->dc.clnt_cred), - &(q_s.cli_creds), &srv_creds)) - { - memcpy(&(p->dc.srv_cred), &(p->dc.clnt_cred), - sizeof(p->dc.clnt_cred)); - } - else - { - status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT; - } + if(!net_reply_sam_logoff(&q_l, rdata, &srv_cred, 0x0)) + return False; - /* construct reply. */ - net_reply_sam_sync(&q_s, rdata, p->dc.sess_key, &srv_creds, status); + return True; } - /************************************************************************* net_login_interactive: *************************************************************************/ -static uint32 net_login_interactive(NET_ID_INFO_1 *id1, - struct sam_passwd *smb_pass, - struct dcinfo *dc) + +static uint32 net_login_interactive(NET_ID_INFO_1 *id1, struct smb_passwd *smb_pass, + user_struct *vuser) { uint32 status = 0x0; @@ -629,14 +543,14 @@ static uint32 net_login_interactive(NET_ID_INFO_1 *id1, unsigned char key[16]; memset(key, 0, 16); - memcpy(key, dc->sess_key, 8); + memcpy(key, vuser->dc.sess_key, 8); memcpy(lm_pwd, id1->lm_owf.data, 16); memcpy(nt_pwd, id1->nt_owf.data, 16); #ifdef DEBUG_PASSWORD DEBUG(100,("key:")); - dump_data(100, key, 16); + dump_data(100, (char *)key, 16); DEBUG(100,("lm owf password:")); dump_data(100, lm_pwd, 16); @@ -645,8 +559,8 @@ static uint32 net_login_interactive(NET_ID_INFO_1 *id1, dump_data(100, nt_pwd, 16); #endif - SamOEMhash((uchar *)lm_pwd, key, 0); - SamOEMhash((uchar *)nt_pwd, key, 0); + SamOEMhash((uchar *)lm_pwd, key, False); + SamOEMhash((uchar *)nt_pwd, key, False); #ifdef DEBUG_PASSWORD DEBUG(100,("decrypt of lm owf password:")); @@ -656,14 +570,7 @@ static uint32 net_login_interactive(NET_ID_INFO_1 *id1, dump_data(100, nt_pwd, 16); #endif - if (smb_pass->smb_nt_passwd == NULL) - { - DEBUG(5,("warning: NETLOGON user %s only has an LM password\n", - smb_pass->unix_name)); - } - if (memcmp(smb_pass->smb_passwd , lm_pwd, 16) != 0 || - smb_pass->smb_nt_passwd == NULL || memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0) { status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD; @@ -675,52 +582,45 @@ static uint32 net_login_interactive(NET_ID_INFO_1 *id1, /************************************************************************* net_login_network: *************************************************************************/ -static uint32 net_login_network(NET_ID_INFO_2 *id2, - struct sam_passwd *sam_pass, - struct dcinfo *dc, - char sess_key[16]) -{ - fstring user; - fstring domain; - - int nt_pw_len = id2->hdr_nt_chal_resp.str_str_len; - int lm_pw_len = id2->hdr_lm_chal_resp.str_str_len; - unistr2_to_ascii(user , &id2->uni_user_name, sizeof(user)-1); - unistr2_to_ascii(domain, &id2->uni_domain_name, sizeof(domain)-1); +static uint32 net_login_network(NET_ID_INFO_2 *id2, struct smb_passwd *smb_pass) +{ + DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n", + id2->hdr_lm_chal_resp.str_str_len, + id2->hdr_nt_chal_resp.str_str_len)); - DEBUG(5,("net_login_network: lm_len:%d nt_len:%d user:%s domain:%s\n", - lm_pw_len, nt_pw_len, user, domain)); + /* JRA. Check the NT password first if it exists - this is a higher quality + password, if it exists and it doesn't match - fail. */ - if (pass_check_smb(pwdb_sam_to_smb(sam_pass), - domain, - id2->lm_chal, - (uchar *)id2->lm_chal_resp.buffer, lm_pw_len, - (uchar *)id2->nt_chal_resp.buffer, nt_pw_len, - NULL, sess_key)) + if (id2->hdr_nt_chal_resp.str_str_len == 24 && + smb_pass->smb_nt_passwd != NULL) { - unsigned char key[16]; - - memset(key, 0, 16); - memcpy(key, dc->sess_key, 8); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("key:")); - dump_data(100, key, 16); - - DEBUG(100,("user sess key:")); - dump_data(100, sess_key, 16); -#endif + if(smb_password_check((char *)id2->nt_chal_resp.buffer, + smb_pass->smb_nt_passwd, + id2->lm_chal)) + return 0x0; + else + return 0xC0000000 | NT_STATUS_WRONG_PASSWORD; + } - SamOEMhash((uchar *)sess_key, key, 0); + /* lkclXXXX this is not a good place to put disabling of LM hashes in. + if that is to be done, first move this entire function into a + library routine that calls the two smb_password_check() functions. + if disabling LM hashes (which nt can do for security reasons) then + an attempt should be made to disable them everywhere (which nt does + not do, for various security-hole reasons). + */ + + if (id2->hdr_lm_chal_resp.str_str_len == 24 && + smb_password_check((char *)id2->lm_chal_resp.buffer, + smb_pass->smb_passwd, + id2->lm_chal)) + { + return 0x0; + } -#ifdef DEBUG_PASSWORD - DEBUG(100,("encrypt of user session key:")); - dump_data(100, sess_key, 16); -#endif - return 0x0; - } + /* oops! neither password check succeeded */ return 0xC0000000 | NT_STATUS_WRONG_PASSWORD; } @@ -728,242 +628,242 @@ static uint32 net_login_network(NET_ID_INFO_2 *id2, /************************************************************************* api_net_sam_logon: *************************************************************************/ -static uint32 reply_net_sam_logon(NET_Q_SAM_LOGON *q_l, - struct dcinfo *dc, - DOM_CRED *srv_cred, NET_USER_INFO_3 *usr_info) -{ - struct sam_passwd *sam_pass = NULL; - UNISTR2 *uni_samusr = NULL; - UNISTR2 *uni_domain = NULL; - fstring nt_username; - char *enc_user_sess_key = NULL; - char sess_key[16]; - - NTTIME logon_time ; - NTTIME logoff_time ; - NTTIME kickoff_time ; - NTTIME pass_last_set_time ; - NTTIME pass_can_change_time ; - NTTIME pass_must_change_time; - - fstring nt_name ; - fstring full_name ; - fstring logon_script; - fstring profile_path; - fstring home_dir ; - fstring dir_drive ; - - uint32 user_rid ; - uint32 group_rid; - - int num_gids = 0; - DOMAIN_GRP *grp_mem = NULL; - DOM_GID *gids = NULL; - - /* checks and updates credentials. creates reply credentials */ - if (!deal_with_creds(dc->sess_key, &(dc->clnt_cred), - &(q_l->sam_id.client.cred), srv_cred)) - { - return 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - - memcpy(&(dc->srv_cred), &(dc->clnt_cred), sizeof(dc->clnt_cred)); - - /* find the username */ - - switch (q_l->sam_id.logon_level) - { - case INTERACTIVE_LOGON_TYPE: - { - uni_samusr = &(q_l->sam_id.ctr->auth.id1.uni_user_name); - uni_domain = &(q_l->sam_id.ctr->auth.id1.uni_domain_name); - - DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", global_sam_name)); - break; - } - case NET_LOGON_TYPE: - { - uni_samusr = &(q_l->sam_id.ctr->auth.id2.uni_user_name); - uni_domain = &(q_l->sam_id.ctr->auth.id2.uni_domain_name); - - DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", global_sam_name)); - break; - } - default: - { - DEBUG(2,("SAM Logon: unsupported switch value\n")); - return 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; - } - } - - /* check username exists */ - - unistr2_to_ascii(nt_username, uni_samusr, - sizeof(nt_username)-1); - DEBUG(3,("User:[%s]\n", nt_username)); - - become_root(True); - sam_pass = getsam21pwntnam(nt_username); - unbecome_root(True); - - if (sam_pass == NULL) - { - return 0xC0000000 | NT_STATUS_NO_SUCH_USER; - } - else if (IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_DISABLED) && - IS_BITS_CLR_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ)) - { - return 0xC0000000 | NT_STATUS_ACCOUNT_DISABLED; - } +static BOOL api_net_sam_logon( uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + NET_Q_SAM_LOGON q_l; + NET_ID_INFO_CTR ctr; + NET_USER_INFO_3 usr_info; + uint32 status = 0x0; + DOM_CRED srv_cred; + struct smb_passwd *smb_pass = NULL; + UNISTR2 *uni_samlogon_user = NULL; + fstring nt_username; + + user_struct *vuser = NULL; + + if ((vuser = get_valid_user_struct(vuid)) == NULL) + return False; + + memset(&q_l, '\0', sizeof(q_l)); + memset(&ctr, '\0', sizeof(ctr)); + memset(&usr_info, '\0', sizeof(usr_info)); + + q_l.sam_id.ctr = &ctr; + + if(!net_io_q_sam_logon("", &q_l, data, 0)) { + DEBUG(0,("api_net_sam_logon: Failed to unmarshall NET_Q_SAM_LOGON.\n")); + return False; + } + + /* checks and updates credentials. creates reply credentials */ + if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), + &(q_l.sam_id.client.cred), &srv_cred)) + status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + else + memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred)); + + /* find the username */ + + if (status == 0) { + switch (q_l.sam_id.logon_level) { + case INTERACTIVE_LOGON_TYPE: + uni_samlogon_user = &q_l.sam_id.ctr->auth.id1.uni_user_name; + + DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup())); + break; + case NET_LOGON_TYPE: + uni_samlogon_user = &q_l.sam_id.ctr->auth.id2.uni_user_name; + + DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup())); + break; + default: + DEBUG(2,("SAM Logon: unsupported switch value\n")); + status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + break; + } /* end switch */ + } /* end if status == 0 */ + + /* check username exists */ + + if (status == 0) { + pstrcpy(nt_username, dos_unistrn2(uni_samlogon_user->buffer, + uni_samlogon_user->uni_str_len)); + + DEBUG(3,("User:[%s]\n", nt_username)); - logon_time = sam_pass->logon_time; - logoff_time = sam_pass->logoff_time; - kickoff_time = sam_pass->kickoff_time; - pass_last_set_time = sam_pass->pass_last_set_time; - pass_can_change_time = sam_pass->pass_can_change_time; - pass_must_change_time = sam_pass->pass_must_change_time; + /* + * Convert to a UNIX username. + */ + map_username(nt_username); - fstrcpy(nt_name , sam_pass->nt_name); - fstrcpy(full_name , sam_pass->full_name); - fstrcpy(logon_script, sam_pass->logon_script); - fstrcpy(profile_path, sam_pass->profile_path); - fstrcpy(home_dir , sam_pass->home_dir); - fstrcpy(dir_drive , sam_pass->dir_drive); + /* + * Do any case conversions. + */ + (void)Get_Pwnam(nt_username, True); + + become_root(True); + smb_pass = getsmbpwnam(nt_username); + unbecome_root(True); + + if (smb_pass == NULL) + status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; + else if (smb_pass->acct_ctrl & ACB_PWNOTREQ) + status = 0; + else if (smb_pass->acct_ctrl & ACB_DISABLED) + status = 0xC0000000 | NT_STATUS_ACCOUNT_DISABLED; + } + + /* Validate password - if required. */ + + if ((status == 0) && !(smb_pass->acct_ctrl & ACB_PWNOTREQ)) { + switch (q_l.sam_id.logon_level) { + case INTERACTIVE_LOGON_TYPE: + /* interactive login. */ + status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, smb_pass, vuser); + break; + case NET_LOGON_TYPE: + /* network login. lm challenge and 24 byte responses */ + status = net_login_network(&q_l.sam_id.ctr->auth.id2, smb_pass); + break; + } + } + + /* lkclXXXX this is the point at which, if the login was + successful, that the SAM Local Security Authority should + record that the user is logged in to the domain. + */ - user_rid = sam_pass->user_rid; - group_rid = sam_pass->group_rid; + /* return the profile plus other bits :-) */ - /* validate password - if required */ + if (status == 0) { + DOM_GID *gids = NULL; + int num_gids = 0; + NTTIME dummy_time; + pstring logon_script; + pstring profile_path; + pstring home_dir; + pstring home_drive; + pstring my_name; + pstring my_workgroup; + pstring domain_groups; + uint32 r_uid; + uint32 r_gid; - if (!(IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ))) - { - uint32 status = 0x0; - switch (q_l->sam_id.logon_level) - { - case INTERACTIVE_LOGON_TYPE: - { - /* interactive login. */ - status = net_login_interactive(&q_l->sam_id.ctr->auth.id1, sam_pass, dc); - break; - } - case NET_LOGON_TYPE: - { - /* network login. lm challenge and 24 byte responses */ - status = net_login_network(&q_l->sam_id.ctr->auth.id2, sam_pass, dc, sess_key); - enc_user_sess_key = sess_key; - break; - } - } - if (status != 0x0) - { - return status; - } - } + /* set up pointer indicating user/password failed to be found */ + usr_info.ptr_user_info = 0; - /* lkclXXXX this is the point at which, if the login was - successful, that the SAM Local Security Authority should - record that the user is logged in to the domain. - */ + dummy_time.low = 0xffffffff; + dummy_time.high = 0x7fffffff; - /* return the profile plus other bits :-) */ + /* XXXX hack to get standard_sub_basic() to use sam logon username */ + /* possibly a better way would be to do a become_user() call */ + sam_logon_in_ssb = True; + pstrcpy(samlogon_user, nt_username); - /* set up pointer indicating user/password failed to be found */ - usr_info->ptr_user_info = 0; + pstrcpy(logon_script, lp_logon_script()); + pstrcpy(profile_path, lp_logon_path()); - if (!getusergroupsntnam(nt_username, &grp_mem, &num_gids)) - { - return 0xC0000000 | NT_STATUS_INVALID_PRIMARY_GROUP; - } + pstrcpy(my_workgroup, lp_workgroup()); - num_gids = make_dom_gids(grp_mem, num_gids, &gids); - - make_net_user_info3(usr_info, - &logon_time, - &logoff_time, - &kickoff_time, - &pass_last_set_time, - &pass_can_change_time, - &pass_must_change_time, - - nt_name , /* user_name */ - full_name , /* full_name */ - logon_script , /* logon_script */ - profile_path , /* profile_path */ - home_dir , /* home_dir */ - dir_drive , /* dir_drive */ - - 0, /* logon_count */ - 0, /* bad_pw_count */ - - user_rid , /* RID user_id */ - group_rid , /* RID group_id */ - num_gids, /* uint32 num_groups */ - gids , /* DOM_GID *gids */ - 0x20 , /* uint32 user_flgs (?) */ - - enc_user_sess_key, /* char sess_key[16] */ - - global_myname , /* char *logon_srv */ - global_sam_name, /* char *logon_dom */ - &global_sam_sid, /* DOM_SID *dom_sid */ - NULL); /* char *other_sids */ - - /* Free any allocated groups array. */ - if (gids) - { - free((char *)gids); - } + pstrcpy(home_drive, lp_logon_drive()); + pstrcpy(home_dir, lp_logon_home()); - return 0x0; -} + pstrcpy(my_name, global_myname); + strupper(my_name); -/************************************************************************* - api_net_sam_logon: - *************************************************************************/ -static void api_net_sam_logon( rpcsrv_struct *p, - prs_struct *data, - prs_struct *rdata) -{ - NET_Q_SAM_LOGON q_l; - NET_ID_INFO_CTR ctr; - NET_USER_INFO_3 usr_info; - uint32 status = 0x0; - DOM_CRED srv_cred; + /* + * This is the point at which we get the group + * database - we should be getting the gid_t list + * from /etc/group and then turning the uids into + * rids and then into machine sids for this user. + * JRA. + */ - q_l.sam_id.ctr = &ctr; - net_io_q_sam_logon("", &q_l, data, 0); + get_domain_user_groups(domain_groups, nt_username); - status = reply_net_sam_logon(&q_l, &p->dc, &srv_cred, &usr_info); - net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status); + /* + * make_dom_gids allocates the gids array. JRA. + */ + gids = NULL; + num_gids = make_dom_gids(domain_groups, &gids); + + sam_logon_in_ssb = False; + + if (pdb_name_to_rid(nt_username, &r_uid, &r_gid)) + init_net_user_info3(&usr_info, + &dummy_time, /* logon_time */ + &dummy_time, /* logoff_time */ + &dummy_time, /* kickoff_time */ + &dummy_time, /* pass_last_set_time */ + &dummy_time, /* pass_can_change_time */ + &dummy_time, /* pass_must_change_time */ + + nt_username , /* user_name */ + vuser->real_name, /* full_name */ + logon_script , /* logon_script */ + profile_path , /* profile_path */ + home_dir , /* home_dir */ + home_drive , /* dir_drive */ + + 0, /* logon_count */ + 0, /* bad_pw_count */ + + r_uid , /* RID user_id */ + r_gid , /* RID group_id */ + num_gids, /* uint32 num_groups */ + gids , /* DOM_GID *gids */ + 0x20 , /* uint32 user_flgs (?) */ + + NULL, /* char sess_key[16] */ + + my_name , /* char *logon_srv */ + my_workgroup, /* char *logon_dom */ + + &global_sam_sid, /* DOM_SID *dom_sid */ + NULL); /* char *other_sids */ + else + status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; + + /* Free any allocated groups array. */ + if(gids) + free((char *)gids); + } + + if(!net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status)) + return False; + + return True; } /************************************************************************* api_net_trust_dom_list: *************************************************************************/ -static void api_net_trust_dom_list( rpcsrv_struct *p, - prs_struct *data, - prs_struct *rdata) + +static BOOL api_net_trust_dom_list( uint16 vuid, + prs_struct *data, + prs_struct *rdata) { NET_Q_TRUST_DOM_LIST q_t; - char **doms = NULL; - uint32 num_doms = 0; - enumtrustdoms(&doms, &num_doms); + char *trusted_domain = "test_domain"; DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__)); /* grab the lsa trusted domain list query... */ - net_io_q_trust_dom("", &q_t, data, 0); + if(!net_io_q_trust_dom("", &q_t, data, 0)) { + DEBUG(0,("api_net_trust_dom_list: Failed to unmarshall NET_Q_TRUST_DOM_LIST.\n")); + return False; + } /* construct reply. */ - net_reply_trust_dom_list(&q_t, rdata, - num_doms, doms); - - free_char_array(num_doms, doms); + if(!net_reply_trust_dom_list(&q_t, rdata, 1, trusted_domain)) + return False; DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__)); + + return True; } @@ -976,7 +876,8 @@ static void api_net_trust_dom_list( rpcsrv_struct *p, /************************************************************************* api_net_logon_ctrl2: *************************************************************************/ -static void api_net_logon_ctrl2( rpcsrv_struct *p, + +static BOOL api_net_logon_ctrl2( uint16 vuid, prs_struct *data, prs_struct *rdata) { @@ -992,14 +893,20 @@ static void api_net_logon_ctrl2( rpcsrv_struct *p, DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__)); /* grab the lsa netlogon ctrl2 query... */ - net_io_q_logon_ctrl2("", &q_l, data, 0); + if(!net_io_q_logon_ctrl2("", &q_l, data, 0)) { + DEBUG(0,("api_net_logon_ctrl2: Failed to unmarshall NET_Q_LOGON_CTRL2.\n")); + return False; + } /* construct reply. */ - net_reply_logon_ctrl2(&q_l, rdata, + if(!net_reply_logon_ctrl2(&q_l, rdata, flags, pdc_connection_status, logon_attempts, - tc_status, trusted_domain); + tc_status, trusted_domain)) + return False; DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__)); + + return True; } /******************************************************************* @@ -1008,21 +915,20 @@ static void api_net_logon_ctrl2( rpcsrv_struct *p, static struct api_struct api_net_cmds [] = { { "NET_REQCHAL" , NET_REQCHAL , api_net_req_chal }, - { "NET_AUTH" , NET_AUTH , api_net_auth }, { "NET_AUTH2" , NET_AUTH2 , api_net_auth_2 }, { "NET_SRVPWSET" , NET_SRVPWSET , api_net_srv_pwset }, { "NET_SAMLOGON" , NET_SAMLOGON , api_net_sam_logon }, { "NET_SAMLOGOFF" , NET_SAMLOGOFF , api_net_sam_logoff }, { "NET_LOGON_CTRL2" , NET_LOGON_CTRL2 , api_net_logon_ctrl2 }, { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list }, - { "NET_SAM_SYNC" , NET_SAM_SYNC , api_net_sam_sync }, - { NULL , 0 , NULL } + { NULL , 0 , NULL } }; /******************************************************************* receives a netlogon pipe and responds. ********************************************************************/ -BOOL api_netlog_rpc(rpcsrv_struct *p, prs_struct *data) + +BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data) { return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data); } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index d15cc1248c..236558ba70 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -1,4 +1,3 @@ - /* * Unix SMB/Netbios implementation. * Version 1.9. @@ -6,6 +5,7 @@ * Copyright (C) Andrew Tridgell 1992-1998 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, * Copyright (C) Paul Ashton 1997-1998. + * Copyright (C) Jeremy Allison 1999. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -43,15 +43,14 @@ extern int DEBUGLEVEL; -static void NTLMSSPcalc_p( rpcsrv_struct *p, unsigned char *data, int len) +static void NTLMSSPcalc_p( pipes_struct *p, unsigned char *data, int len) { unsigned char *hash = p->ntlmssp_hash; unsigned char index_i = hash[256]; unsigned char index_j = hash[257]; int ind; - for( ind = 0; ind < len; ind++) - { + for( ind = 0; ind < len; ind++) { unsigned char tc; unsigned char t; @@ -71,250 +70,332 @@ static void NTLMSSPcalc_p( rpcsrv_struct *p, unsigned char *data, int len) } /******************************************************************* - frees all temporary data used in construction of pdu + Generate the next PDU to be returned from the data in p->rdata. + We cheat here as this function doesn't handle the special auth + footers of the authenticated bind response reply. ********************************************************************/ -void rpcsrv_free_temp(rpcsrv_struct *l) + +BOOL create_next_pdu(pipes_struct *p) { - mem_free_data(l->rhdr .data); - mem_free_data(l->rfault .data); - mem_free_data(l->rdata_i.data); - mem_free_data(l->rauth .data); - mem_free_data(l->rverf .data); - mem_free_data(l->rntlm .data); -} + RPC_HDR_RESP hdr_resp; + BOOL auth_verify = IS_BITS_SET_ALL(p->ntlmssp_chal_flags, NTLMSSP_NEGOTIATE_SIGN); + BOOL auth_seal = IS_BITS_SET_ALL(p->ntlmssp_chal_flags, NTLMSSP_NEGOTIATE_SEAL); + uint32 data_len; + uint32 data_space_available; + uint32 data_len_left; + prs_struct outgoing_pdu; + char *data; + char *data_from; + uint32 data_pos; -/******************************************************************* - turns a DCE/RPC request into a DCE/RPC reply + memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); - this is where the data really should be split up into an array of - headers and data sections. + /* Change the incoming request header to a response. */ + p->hdr.pkt_type = RPC_RESPONSE; - ********************************************************************/ -BOOL create_rpc_reply(rpcsrv_struct *l, uint32 data_start) -{ - char *data; - BOOL auth_verify = IS_BITS_SET_ALL(l->ntlmssp_chal.neg_flags, NTLMSSP_NEGOTIATE_SIGN); - BOOL auth_seal = IS_BITS_SET_ALL(l->ntlmssp_chal.neg_flags, NTLMSSP_NEGOTIATE_SEAL); - uint32 data_len; - uint32 auth_len; - uint32 data_end = l->rdata.offset + (l->ntlmssp_auth ? (8 + 16) : 0); + /* Set up rpc header flags. */ + if (p->data_sent_length == 0) + p->hdr.flags = RPC_FLG_FIRST; + else + p->hdr.flags = 0; - DEBUG(5,("create_rpc_reply: data_start: %d data_end: %d max_tsize: %d\n", - data_start, data_end, l->hdr_ba.bba.max_tsize)); + /* + * Work out how much we can fit in a sigle PDU. + */ - auth_len = l->hdr.auth_len; + data_space_available = sizeof(p->current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; + if(p->ntlmssp_auth_validated) + data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN); - if (l->ntlmssp_auth) - { - DEBUG(10,("create_rpc_reply: auth\n")); - if (auth_len != 16) - { - return False; - } - } + /* + * The amount we send is the minimum of the available + * space and the amount left to send. + */ - prs_init(&l->rhdr , 0x18, 4, 0, False); - prs_init(&l->rauth, 1024, 4, 0, False); - prs_init(&l->rverf, 0x10, 4, 0, False); + data_len_left = prs_offset(&p->rdata) - p->data_sent_length; - l->hdr.pkt_type = RPC_RESPONSE; /* mark header as an rpc response */ + /* + * Ensure there really is data left to send. + */ - /* set up rpc header (fragmentation issues) */ - if (data_start == 0) - { - l->hdr.flags = RPC_FLG_FIRST; - } - else - { - l->hdr.flags = 0; + if(!data_len_left) { + DEBUG(0,("create_next_pdu: no data left to send !\n")); + return False; } - l->hdr_resp.alloc_hint = data_end - data_start; /* calculate remaining data to be sent */ + data_len = MIN(data_len_left, data_space_available); - if (l->hdr_resp.alloc_hint + 0x18 <= l->hdr_ba.bba.max_tsize) - { - l->hdr.flags |= RPC_FLG_LAST; - l->hdr.frag_len = l->hdr_resp.alloc_hint + 0x18; - } - else - { - l->hdr.frag_len = l->hdr_ba.bba.max_tsize; - } + /* + * Set up the alloc hint. This should be the data left to + * send. + */ - if (l->ntlmssp_auth) - { - l->hdr_resp.alloc_hint -= auth_len + 8; + hdr_resp.alloc_hint = data_len_left; + + /* + * Set up the header lengths. + */ + + if (p->ntlmssp_auth_validated) { + p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + + RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN; + p->hdr.auth_len = RPC_AUTH_NTLMSSP_CHK_LEN; + } else { + p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len; + p->hdr.auth_len = 0; } - if (l->ntlmssp_auth) - { - data_len = l->hdr.frag_len - auth_len - (auth_verify ? 8 : 0) - 0x18; + /* + * Work out if this PDU will be the last. + */ + + if(p->data_sent_length + data_len >= prs_offset(&p->rdata)) + p->hdr.flags |= RPC_FLG_LAST; + + /* + * Init the parse struct to point at the outgoing + * data. + */ + + prs_init( &outgoing_pdu, 0, 4, MARSHALL); + prs_give_memory( &outgoing_pdu, (char *)p->current_pdu, sizeof(p->current_pdu), False); + + /* Store the header in the data stream. */ + if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) { + DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR.\n")); + return False; } - else - { - data_len = l->hdr.frag_len - 0x18; + + if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) { + DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_RESP.\n")); + return False; } - l->rhdr.data->offset.start = 0; - l->rhdr.data->offset.end = 0x18; + /* Store the current offset. */ + data_pos = prs_offset(&outgoing_pdu); - /* store the header in the data stream */ - smb_io_rpc_hdr ("hdr" , &(l->hdr ), &(l->rhdr), 0); - smb_io_rpc_hdr_resp("resp", &(l->hdr_resp), &(l->rhdr), 0); + /* Copy the data into the PDU. */ + data_from = prs_data_p(&p->rdata) + p->data_sent_length; + + if(!prs_append_data(&outgoing_pdu, data_from, data_len)) { + DEBUG(0,("create_next_pdu: failed to copy %u bytes of data.\n", (unsigned int)data_len)); + return False; + } - /* don't use rdata: use rdata_i instead, which moves... */ - /* make a pointer to the rdata data, NOT A COPY */ + /* + * Set data to point to where we copied the data into. + */ - l->rdata_i.data = NULL; - prs_init(&l->rdata_i, 0, l->rdata.align, l->rdata.data->margin, l->rdata.io); - data = mem_data(&(l->rdata.data), data_start); - mem_create(l->rdata_i.data, data, 0, data_len, 0, False); - l->rdata_i.offset = data_len; + data = prs_data_p(&outgoing_pdu) + data_pos; - if (auth_len > 0) - { + if (p->hdr.auth_len > 0) { uint32 crc32 = 0; - DEBUG(5,("create_rpc_reply: sign: %s seal: %s data %d auth %d\n", - BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len, auth_len)); + DEBUG(5,("create_next_pdu: sign: %s seal: %s data %d auth %d\n", + BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len, p->hdr.auth_len)); - if (auth_seal) - { - crc32 = crc32_calc_buffer(data_len, data); - NTLMSSPcalc_p(l, (uchar*)data, data_len); + if (auth_seal) { + crc32 = crc32_calc_buffer(data, data_len); + NTLMSSPcalc_p(p, (uchar*)data, data_len); } - if (auth_seal || auth_verify) - { - make_rpc_hdr_auth(&l->auth_info, 0x0a, 0x06, 0x08, (auth_verify ? 1 : 0)); - smb_io_rpc_hdr_auth("hdr_auth", &l->auth_info, &l->rauth, 0); + if (auth_seal || auth_verify) { + RPC_HDR_AUTH auth_info; + + init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, NTLMSSP_AUTH_LEVEL, + (auth_verify ? RPC_HDR_AUTH_LEN : 0), (auth_verify ? 1 : 0)); + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { + DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n")); + return False; + } } - if (auth_verify) - { - char *auth_data; - l->ntlmssp_seq_num++; - make_rpc_auth_ntlmssp_chk(&l->ntlmssp_chk, NTLMSSP_SIGN_VERSION, crc32, l->ntlmssp_seq_num++); - smb_io_rpc_auth_ntlmssp_chk("auth_sign", &(l->ntlmssp_chk), &l->rverf, 0); - auth_data = mem_data(&l->rverf.data, 4); - NTLMSSPcalc_p(l, (uchar*)auth_data, 12); + if (auth_verify) { + RPC_AUTH_NTLMSSP_CHK ntlmssp_chk; + char *auth_data = prs_data_p(&outgoing_pdu); + + p->ntlmssp_seq_num++; + init_rpc_auth_ntlmssp_chk(&ntlmssp_chk, NTLMSSP_SIGN_VERSION, + crc32, p->ntlmssp_seq_num++); + auth_data = prs_data_p(&outgoing_pdu) + prs_offset(&outgoing_pdu) + 4; + if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, &outgoing_pdu, 0)) { + DEBUG(0,("create_next_pdu: failed to marshall RPC_AUTH_NTLMSSP_CHK.\n")); + return False; + } + NTLMSSPcalc_p(p, (uchar*)auth_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4); } } - /* set up the data chain */ - if (l->ntlmssp_auth) - { - prs_link(NULL , &l->rhdr , &l->rdata_i); - prs_link(&l->rhdr , &l->rdata_i, &l->rauth ); - prs_link(&l->rdata_i, &l->rauth , &l->rverf ); - prs_link(&l->rauth , &l->rverf , NULL ); - } - else - { - prs_link(NULL , &l->rhdr , &l->rdata_i); - prs_link(&l->rhdr, &l->rdata_i, NULL ); - } + /* + * Setup the counts for this PDU. + */ - return l->rhdr.data != NULL && l->rhdr.offset == 0x18; + p->data_sent_length += data_len; + p->current_pdu_len = p->hdr.frag_len; + p->current_pdu_sent = 0; + + return True; } -static BOOL api_pipe_ntlmssp_verify(rpcsrv_struct *l) +/******************************************************************* + Process an NTLMSSP authentication response. + If this function succeeds, the user has been authenticated + and their domain, name and calling workstation stored in + the pipe struct. + The initial challenge is stored in p->challenge. + *******************************************************************/ + +static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlmssp_resp) { - uchar *pwd = NULL; - uchar null_pwd[16]; uchar lm_owf[24]; - uchar nt_owf[128]; - size_t lm_owf_len; - size_t nt_owf_len; - size_t usr_len; - size_t dom_len; - size_t wks_len; - BOOL anonymous = False; + uchar nt_owf[24]; + fstring user_name; + fstring unix_user_name; + fstring domain; + fstring wks; + BOOL guest_user = False; + struct smb_passwd *smb_pass = NULL; + struct passwd *pass = NULL; + uchar null_smb_passwd[16]; + uchar *smb_passwd_ptr = NULL; + + DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n")); - memset(null_pwd, 0, sizeof(null_pwd)); + memset(p->user_name, '\0', sizeof(p->user_name)); + memset(p->unix_user_name, '\0', sizeof(p->unix_user_name)); + memset(p->domain, '\0', sizeof(p->domain)); + memset(p->wks, '\0', sizeof(p->wks)); - DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n")); + /* + * Setup an empty password for a guest user. + */ - lm_owf_len = l->ntlmssp_resp.hdr_lm_resp.str_str_len; - nt_owf_len = l->ntlmssp_resp.hdr_nt_resp.str_str_len; - usr_len = l->ntlmssp_resp.hdr_usr .str_str_len; - dom_len = l->ntlmssp_resp.hdr_domain .str_str_len; - wks_len = l->ntlmssp_resp.hdr_wks .str_str_len; + memset(null_smb_passwd,0,16); - if (lm_owf_len == 0 && nt_owf_len == 0 && - usr_len == 0 && dom_len == 0 && wks_len == 0) - { - anonymous = True; - } - else - { - if (lm_owf_len == 0) return False; - if (nt_owf_len == 0) return False; - if (l->ntlmssp_resp.hdr_usr .str_str_len == 0) return False; - if (l->ntlmssp_resp.hdr_domain .str_str_len == 0) return False; - if (l->ntlmssp_resp.hdr_wks .str_str_len == 0) return False; + /* + * We always negotiate UNICODE. + */ + + if (IS_BITS_SET_ALL(p->ntlmssp_chal_flags, NTLMSSP_NEGOTIATE_UNICODE)) { + fstrcpy(user_name, dos_unistrn2((uint16*)ntlmssp_resp->user, ntlmssp_resp->hdr_usr.str_str_len/2)); + fstrcpy(domain, dos_unistrn2((uint16*)ntlmssp_resp->domain, ntlmssp_resp->hdr_domain.str_str_len/2)); + fstrcpy(wks, dos_unistrn2((uint16*)ntlmssp_resp->wks, ntlmssp_resp->hdr_wks.str_str_len/2)); + } else { + fstrcpy(user_name, ntlmssp_resp->user); + fstrcpy(domain, ntlmssp_resp->domain); + fstrcpy(wks, ntlmssp_resp->wks); } - if (lm_owf_len > sizeof(lm_owf)) return False; - if (nt_owf_len > sizeof(nt_owf)) return False; + DEBUG(5,("user: %s domain: %s wks: %s\n", user_name, domain, wks)); - memcpy(lm_owf, l->ntlmssp_resp.lm_resp, sizeof(lm_owf)); - memcpy(nt_owf, l->ntlmssp_resp.nt_resp, sizeof(nt_owf)); + memcpy(lm_owf, ntlmssp_resp->lm_resp, sizeof(lm_owf)); + memcpy(nt_owf, ntlmssp_resp->nt_resp, sizeof(nt_owf)); #ifdef DEBUG_PASSWORD DEBUG(100,("lm, nt owfs, chal\n")); - dump_data(100, lm_owf, sizeof(lm_owf)); - dump_data(100, nt_owf, sizeof(nt_owf)); - dump_data(100, l->ntlmssp_chal.challenge, 8); + dump_data(100, (char *)lm_owf, sizeof(lm_owf)); + dump_data(100, (char *)nt_owf, sizeof(nt_owf)); + dump_data(100, (char *)p->challenge, 8); #endif - memset(l->user_name, 0, sizeof(l->user_name)); - memset(l->domain , 0, sizeof(l->domain )); - memset(l->wks , 0, sizeof(l->wks )); + /* + * Allow guest access. Patch from Shirish Kalele . + */ + + if((strlen(user_name) == 0) && (ntlmssp_resp->hdr_lm_resp.str_str_len==0) && + (ntlmssp_resp->hdr_nt_resp.str_str_len==0)) { + + guest_user = True; + + fstrcpy(unix_user_name, lp_guestaccount(-1)); + DEBUG(100,("Null user in NTLMSSP verification. Using guest = %s\n", unix_user_name)); + + smb_passwd_ptr = null_smb_passwd; + + } else { + + /* + * Pass the user through the NT -> unix user mapping + * function. + */ + + fstrcpy(unix_user_name, user_name); + (void)map_username(unix_user_name); + + /* + * Do the length checking only if user is not NULL. + */ + + if (ntlmssp_resp->hdr_lm_resp.str_str_len == 0) + return False; + if (ntlmssp_resp->hdr_nt_resp.str_str_len == 0) + return False; + if (ntlmssp_resp->hdr_usr.str_str_len == 0) + return False; + if (ntlmssp_resp->hdr_domain.str_str_len == 0) + return False; + if (ntlmssp_resp->hdr_wks.str_str_len == 0) + return False; - if (IS_BITS_SET_ALL(l->ntlmssp_chal.neg_flags, NTLMSSP_NEGOTIATE_UNICODE)) - { - unibuf_to_ascii(l->user_name, l->ntlmssp_resp.user, - MIN(l->ntlmssp_resp.hdr_usr .str_str_len/2, - sizeof(l->user_name)-1)); - unibuf_to_ascii(l->domain , l->ntlmssp_resp.domain, - MIN(l->ntlmssp_resp.hdr_domain.str_str_len/2, - sizeof(l->domain )-1)); - unibuf_to_ascii(l->wks , l->ntlmssp_resp.wks, - MIN(l->ntlmssp_resp.hdr_wks .str_str_len/2, - sizeof(l->wks )-1)); - } - else - { - fstrcpy(l->user_name, l->ntlmssp_resp.user ); - fstrcpy(l->domain , l->ntlmssp_resp.domain); - fstrcpy(l->wks , l->ntlmssp_resp.wks ); } + /* + * Find the user in the unix password db. + */ - if (anonymous) - { - DEBUG(5,("anonymous user session\n")); - mdfour(l->user_sess_key, null_pwd, 16); - pwd = null_pwd; - l->ntlmssp_validated = True; + if(!(pass = Get_Pwnam(unix_user_name,True))) { + DEBUG(1,("Couldn't find user '%s' in UNIX password database.\n",unix_user_name)); + return(False); } - else - { - DEBUG(5,("user: %s domain: %s wks: %s\n", l->user_name, l->domain, l->wks)); - become_root(False); - l->ntlmssp_validated = check_domain_security(l->user_name, l->domain, - (uchar*)l->ntlmssp_chal.challenge, - lm_owf, lm_owf_len, - nt_owf, nt_owf_len, - l->user_sess_key); - unbecome_root(False); + + if(!guest_user) { + + become_root(True); + + if(!(p->ntlmssp_auth_validated = pass_check_smb(unix_user_name, domain, + (uchar*)p->challenge, lm_owf, nt_owf, NULL))) { + DEBUG(1,("api_pipe_ntlmssp_verify: User %s\\%s from machine %s \ +failed authentication on named pipe %s.\n", domain, unix_user_name, wks, p->name )); + unbecome_root(True); + return False; + } + + if(!(smb_pass = getsmbpwnam(unix_user_name))) { + DEBUG(1,("api_pipe_ntlmssp_verify: Cannot find user %s in smb passwd database.\n", + unix_user_name)); + unbecome_root(True); + return False; + } + + unbecome_root(True); + + if (smb_pass == NULL) { + DEBUG(1,("api_pipe_ntlmssp_verify: Couldn't find user '%s' in smb_passwd file.\n", + unix_user_name)); + return(False); + } + + /* Quit if the account was disabled. */ + if((smb_pass->acct_ctrl & ACB_DISABLED) || !smb_pass->smb_passwd) { + DEBUG(1,("Account for user '%s' was disabled.\n", unix_user_name)); + return(False); + } + + if(!smb_pass->smb_nt_passwd) { + DEBUG(1,("Account for user '%s' has no NT password hash.\n", unix_user_name)); + return(False); + } + + smb_passwd_ptr = smb_pass->smb_passwd; } - if (l->ntlmssp_validated && pwd != NULL) + /* + * Set up the sign/seal data. + */ + { uchar p24[24]; - NTLMSSPOWFencrypt(pwd, lm_owf, p24); + NTLMSSPOWFencrypt(smb_passwd_ptr, lm_owf, p24); { unsigned char j = 0; int ind; @@ -327,761 +408,670 @@ static BOOL api_pipe_ntlmssp_verify(rpcsrv_struct *l) k2[7] = 0xb0; for (ind = 0; ind < 256; ind++) - { - l->ntlmssp_hash[ind] = (unsigned char)ind; - } + p->ntlmssp_hash[ind] = (unsigned char)ind; - for( ind = 0; ind < 256; ind++) - { + for( ind = 0; ind < 256; ind++) { unsigned char tc; - j += (l->ntlmssp_hash[ind] + k2[ind%8]); + j += (p->ntlmssp_hash[ind] + k2[ind%8]); - tc = l->ntlmssp_hash[ind]; - l->ntlmssp_hash[ind] = l->ntlmssp_hash[j]; - l->ntlmssp_hash[j] = tc; + tc = p->ntlmssp_hash[ind]; + p->ntlmssp_hash[ind] = p->ntlmssp_hash[j]; + p->ntlmssp_hash[j] = tc; } - l->ntlmssp_hash[256] = 0; - l->ntlmssp_hash[257] = 0; + p->ntlmssp_hash[256] = 0; + p->ntlmssp_hash[257] = 0; } - l->ntlmssp_seq_num = 0; - } - else - { - l->ntlmssp_validated = False; +/* NTLMSSPhash(p->ntlmssp_hash, p24); */ + p->ntlmssp_seq_num = 0; + } - return l->ntlmssp_validated; -} + fstrcpy(p->user_name, user_name); + fstrcpy(p->unix_user_name, unix_user_name); + fstrcpy(p->domain, domain); + fstrcpy(p->wks, wks); -static BOOL api_pipe_ntlmssp(rpcsrv_struct *l, prs_struct *pd) -{ - /* receive a negotiate; send a challenge; receive a response */ - switch (l->auth_verifier.msg_type) - { - case NTLMSSP_NEGOTIATE: - { - smb_io_rpc_auth_ntlmssp_neg("", &l->ntlmssp_neg, pd, 0); - break; - } - case NTLMSSP_AUTH: - { - smb_io_rpc_auth_ntlmssp_resp("", &l->ntlmssp_resp, pd, 0); - if (!api_pipe_ntlmssp_verify(l)) - { - pd->offset = 0; - } - break; - } - default: - { - /* NTLMSSP expected: unexpected message type */ - DEBUG(3,("unexpected message type in NTLMSSP %d\n", - l->auth_verifier.msg_type)); - return False; - } - } + /* + * Store the UNIX credential data (uid/gid pair) in the pipe structure. + */ + + p->uid = pass->pw_uid; + p->gid = pass->pw_gid; - return (pd->offset != 0); + p->ntlmssp_auth_validated = True; + return True; } +/******************************************************************* + The switch table for the pipe names and the functions to handle them. + *******************************************************************/ + struct api_cmd { char * pipe_clnt_name; char * pipe_srv_name; - BOOL (*fn) (rpcsrv_struct *, prs_struct *); + BOOL (*fn) (pipes_struct *, prs_struct *); }; -static struct api_cmd **api_fd_commands = NULL; -uint32 num_cmds = 0; - -static void api_cmd_free(struct api_cmd *item) -{ - if (item != NULL) - { - if (item->pipe_clnt_name != NULL) - { - free(item->pipe_clnt_name); - } - if (item->pipe_srv_name != NULL) - { - free(item->pipe_srv_name); - } - free(item); - } -} - -static struct api_cmd *api_cmd_dup(const struct api_cmd *from) +static struct api_cmd api_fd_commands[] = { - struct api_cmd *copy = NULL; - if (from == NULL) - { - return NULL; - } - copy = (struct api_cmd *) malloc(sizeof(struct api_cmd)); - if (copy != NULL) - { - ZERO_STRUCTP(copy); - if (from->pipe_clnt_name != NULL) - { - copy->pipe_clnt_name = strdup(from->pipe_clnt_name ); - } - if (from->pipe_srv_name != NULL) - { - copy->pipe_srv_name = strdup(from->pipe_srv_name); - } - if (from->fn != NULL) - { - copy->fn = from->fn; - } - } - return copy; -} + { "lsarpc", "lsass", api_ntlsa_rpc }, + { "samr", "lsass", api_samr_rpc }, + { "srvsvc", "ntsvcs", api_srvsvc_rpc }, + { "wkssvc", "ntsvcs", api_wkssvc_rpc }, + { "NETLOGON", "lsass", api_netlog_rpc }, +#if DISABLED_IN_2_0 + { "winreg", "winreg", api_reg_rpc }, +#endif + { NULL, NULL, NULL } +}; -static void free_api_cmd_array(uint32 num_entries, struct api_cmd **entries) -{ - void(*fn)(void*) = (void(*)(void*))&api_cmd_free; - free_void_array(num_entries, (void**)entries, *fn); -} +/******************************************************************* + This is the client reply to our challenge for an authenticated + bind request. The challenge we sent is in p->challenge. +*******************************************************************/ -static struct api_cmd* add_api_cmd_to_array(uint32 *len, - struct api_cmd ***array, - const struct api_cmd *name) +static BOOL api_pipe_bind_auth_resp(pipes_struct *p, prs_struct *pd) { - void*(*fn)(const void*) = (void*(*)(const void*))&api_cmd_dup; - return (struct api_cmd*)add_copy_to_array(len, - (void***)array, (const void*)name, *fn, False); - -} + RPC_HDR_AUTHA autha_info; + RPC_AUTH_VERIFIER auth_verifier; + RPC_AUTH_NTLMSSP_RESP ntlmssp_resp; + DEBUG(5,("api_pipe_bind_auth_resp: decode request. %d\n", __LINE__)); -void close_msrpc_command_processor(void) -{ - free_api_cmd_array(num_cmds, api_fd_commands); -} + if (p->hdr.auth_len == 0) { + DEBUG(0,("api_pipe_bind_auth_resp: No auth field sent !\n")); + return False; + } -void add_msrpc_command_processor(char* pipe_name, - char* process_name, - BOOL (*fn) (rpcsrv_struct *, prs_struct *)) -{ - struct api_cmd cmd; - cmd.pipe_clnt_name = pipe_name; - cmd.pipe_srv_name = process_name; - cmd.fn = fn; + /* + * Decode the authentication verifier response. + */ - add_api_cmd_to_array(&num_cmds, &api_fd_commands, &cmd); -} + if(!smb_io_rpc_hdr_autha("", &autha_info, pd, 0)) { + DEBUG(0,("api_pipe_bind_auth_resp: unmarshall of RPC_HDR_AUTHA failed.\n")); + return False; + } -static BOOL api_pipe_bind_auth_resp(rpcsrv_struct *l, prs_struct *pd) -{ - DEBUG(5,("api_pipe_bind_auth_resp: decode request. %d\n", __LINE__)); + if (autha_info.auth_type != NTLMSSP_AUTH_TYPE || autha_info.auth_level != NTLMSSP_AUTH_LEVEL) { + DEBUG(0,("api_pipe_bind_auth_resp: incorrect auth type (%d) or level (%d).\n", + (int)autha_info.auth_type, (int)autha_info.auth_level )); + return False; + } - if (l->hdr.auth_len == 0) return False; + if(!smb_io_rpc_auth_verifier("", &auth_verifier, pd, 0)) { + DEBUG(0,("api_pipe_bind_auth_resp: unmarshall of RPC_AUTH_VERIFIER failed.\n")); + return False; + } - /* decode the authentication verifier response */ - smb_io_rpc_hdr_autha("", &l->autha_info, pd, 0); - if (pd->offset == 0) return False; + /* + * Ensure this is a NTLMSSP_AUTH packet type. + */ - if (!rpc_hdr_auth_chk(&(l->auth_info))) return False; + if (!rpc_auth_verifier_chk(&auth_verifier, "NTLMSSP", NTLMSSP_AUTH)) { + DEBUG(0,("api_pipe_bind_auth_resp: rpc_auth_verifier_chk failed.\n")); + return False; + } - smb_io_rpc_auth_ntlmssp_verifier("", &l->auth_verifier, pd, 0); - if (pd->offset == 0) return False; + if(!smb_io_rpc_auth_ntlmssp_resp("", &ntlmssp_resp, pd, 0)) { + DEBUG(0,("api_pipe_bind_auth_resp: Failed to unmarshall RPC_AUTH_NTLMSSP_RESP.\n")); + return False; + } - if (!rpc_auth_ntlmssp_verifier_chk(&(l->auth_verifier), "NTLMSSP", NTLMSSP_AUTH)) return False; + /* + * The following call actually checks the challenge/response data. + * for correctness against the given DOMAIN\user name. + */ - return api_pipe_ntlmssp(l, pd); + if (!api_pipe_ntlmssp_verify(p, &ntlmssp_resp)) + return False; + + return True; } -static BOOL api_pipe_fault_resp(rpcsrv_struct *l, prs_struct *pd, uint32 status) +/******************************************************************* + Marshall a bind_nak pdu. +*******************************************************************/ + +static BOOL setup_bind_nak(pipes_struct *p, prs_struct *pd) { - DEBUG(5,("api_pipe_fault_resp: make response\n")); + prs_struct outgoing_rpc; + RPC_HDR nak_hdr; + uint16 zero = 0; + + /* + * Marshall directly into the outgoing PDU space. We + * must do this as we need to set to the bind response + * header and are never sending more than one PDU here. + */ - prs_init(&(l->rhdr ), 0x18, 4, 0, False); - prs_init(&(l->rfault ), 0x8 , 4, 0, False); + prs_init( &outgoing_rpc, 0, 4, MARSHALL); + prs_give_memory( &outgoing_rpc, (char *)p->current_pdu, sizeof(p->current_pdu), False); - /***/ - /*** set up the header, response header and fault status ***/ - /***/ - l->hdr_fault.status = status; - l->hdr_fault.reserved = 0x0; + /* + * Initialize a bind_nak header. + */ - l->hdr_resp.alloc_hint = 0x0; - l->hdr_resp.cancel_count = 0x0; - l->hdr_resp.reserved = 0x0; + init_rpc_hdr(&nak_hdr, RPC_BINDNACK, RPC_FLG_FIRST | RPC_FLG_LAST, + p->hdr.call_id, RPC_HEADER_LEN + sizeof(uint16), 0); - make_rpc_hdr(&l->hdr, RPC_FAULT, RPC_FLG_NOCALL | RPC_FLG_FIRST | RPC_FLG_LAST, - l->hdr.call_id, - 0x20, - 0); + /* + * Marshall the header into the outgoing PDU. + */ - smb_io_rpc_hdr ("hdr" , &(l->hdr ), &(l->rhdr), 0); - smb_io_rpc_hdr_resp ("resp" , &(l->hdr_resp ), &(l->rhdr), 0); - smb_io_rpc_hdr_fault("fault", &(l->hdr_fault), &(l->rfault), 0); - mem_realloc_data(l->rhdr.data, l->rhdr.offset); - mem_realloc_data(l->rfault.data, l->rfault.offset); + if(!smb_io_rpc_hdr("", &nak_hdr, &outgoing_rpc, 0)) { + DEBUG(0,("setup_bind_nak: marshalling of RPC_HDR failed.\n")); + return False; + } - /***/ - /*** link rpc header and fault together ***/ - /***/ + /* + * Now add the reject reason. + */ - prs_link(NULL , &l->rhdr , &l->rfault); - prs_link(&l->rhdr, &l->rfault, NULL ); + if(!prs_uint16("reject code", &outgoing_rpc, 0, &zero)) + return False; + + p->data_sent_length = 0; + p->current_pdu_len = prs_offset(&outgoing_rpc); + p->current_pdu_sent = 0; return True; } -static BOOL srv_pipe_bind_and_alt_req(rpcsrv_struct *l, prs_struct *pd, - const char* ack_pipe_name, - enum RPC_PKT_TYPE pkt_type) +/******************************************************************* + Respond to a pipe bind request. +*******************************************************************/ + +static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) { + RPC_HDR_BA hdr_ba; + RPC_HDR_RB hdr_rb; + RPC_HDR_AUTH auth_info; uint16 assoc_gid; + fstring ack_pipe_name; + prs_struct out_hdr_ba; + prs_struct out_auth; + prs_struct outgoing_rpc; + int i = 0; + int auth_len = 0; + + p->ntlmssp_auth_requested = False; + + DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__)); + + /* + * Try and find the correct pipe name to ensure + * that this is a pipe name we support. + */ - l->ntlmssp_auth = False; + for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) { + if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) && + api_fd_commands[i].fn != NULL) { + DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", + api_fd_commands[i].pipe_clnt_name, + api_fd_commands[i].pipe_srv_name)); + fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name); + break; + } + } + + if (api_fd_commands[i].fn == NULL) { + DEBUG(3,("api_pipe_bind_req: Unknown pipe name %s in bind request.\n", + p->name )); + if(!setup_bind_nak(p, pd)) + return False; + return True; + } /* decode the bind request */ - smb_io_rpc_hdr_rb("", &l->hdr_rb, pd, 0); + if(!smb_io_rpc_hdr_rb("", &hdr_rb, pd, 0)) { + DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_RB struct.\n")); + return False; + } - if (pd->offset == 0) return False; + /* + * Check if this is an authenticated request. + */ - if (l->hdr.auth_len != 0) - { - /* decode the authentication verifier */ - smb_io_rpc_hdr_auth ("", &l->auth_info , pd, 0); - if (pd->offset == 0) return False; + if (p->hdr.auth_len != 0) { + RPC_AUTH_VERIFIER auth_verifier; + RPC_AUTH_NTLMSSP_NEG ntlmssp_neg; - l->ntlmssp_auth = l->auth_info.auth_type = 0x0a; + /* + * Decode the authentication verifier. + */ - if (l->ntlmssp_auth) - { - smb_io_rpc_auth_ntlmssp_verifier("", &l->auth_verifier, pd, 0); - if (pd->offset == 0) return False; + if(!smb_io_rpc_hdr_auth("", &auth_info, pd, 0)) { + DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_AUTH struct.\n")); + return False; + } - l->ntlmssp_auth = strequal(l->auth_verifier.signature, "NTLMSSP"); + /* + * We only support NTLMSSP_AUTH_TYPE requests. + */ + + if(auth_info.auth_type != NTLMSSP_AUTH_TYPE) { + DEBUG(0,("api_pipe_bind_req: unknown auth type %x requested.\n", + auth_info.auth_type )); + return False; } - if (l->ntlmssp_auth) - { - if (!api_pipe_ntlmssp(l, pd)) return False; + if(!smb_io_rpc_auth_verifier("", &auth_verifier, pd, 0)) { + DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_AUTH struct.\n")); + return False; + } + + if(!strequal(auth_verifier.signature, "NTLMSSP")) { + DEBUG(0,("api_pipe_bind_req: auth_verifier.signature != NTLMSSP\n")); + return False; + } + + if(auth_verifier.msg_type != NTLMSSP_NEGOTIATE) { + DEBUG(0,("api_pipe_bind_req: auth_verifier.msg_type (%d) != NTLMSSP_NEGOTIATE\n", + auth_verifier.msg_type)); + return False; } + + if(!smb_io_rpc_auth_ntlmssp_neg("", &ntlmssp_neg, pd, 0)) { + DEBUG(0,("api_pipe_bind_req: Failed to unmarshall RPC_AUTH_NTLMSSP_NEG.\n")); + return False; + } + + p->ntlmssp_chal_flags = SMBD_NTLMSSP_NEG_FLAGS; + p->ntlmssp_auth_requested = True; } + /* name has to be \PIPE\xxxxx */ + fstrcpy(ack_pipe_name, "\\PIPE\\"); + fstrcat(ack_pipe_name, p->pipe_srv_name); + DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); - prs_init(&(l->rdata), 1024, 4, 0, False); - prs_init(&(l->rhdr ), 0x18, 4, 0, False); - prs_init(&(l->rauth), 1024, 4, 0, False); - prs_init(&(l->rverf), 0x08, 4, 0, False); - prs_init(&(l->rntlm), 1024, 4, 0, False); + /* + * Marshall directly into the outgoing PDU space. We + * must do this as we need to set to the bind response + * header and are never sending more than one PDU here. + */ - /***/ - /*** do the bind ack first ***/ - /***/ + prs_init( &outgoing_rpc, 0, 4, MARSHALL); + prs_give_memory( &outgoing_rpc, (char *)p->current_pdu, sizeof(p->current_pdu), False); - if (l->ntlmssp_auth) - { - assoc_gid = 0x7a77; + /* + * Setup the memory to marshall the ba header, and the + * auth footers. + */ + + if(!prs_init(&out_hdr_ba, 1024, 4, MARSHALL)) { + DEBUG(0,("api_pipe_bind_req: malloc out_hdr_ba failed.\n")); + return False; } - else - { - assoc_gid = l->hdr_rb.bba.assoc_gid; + + if(!prs_init(&out_auth, 1024, 4, MARSHALL)) { + DEBUG(0,("pi_pipe_bind_req: malloc out_auth failed.\n")); + prs_mem_free(&out_hdr_ba); + return False; } - make_rpc_hdr_ba(&l->hdr_ba, - l->hdr_rb.bba.max_tsize, - l->hdr_rb.bba.max_rsize, + if (p->ntlmssp_auth_requested) + assoc_gid = 0x7a77; + else + assoc_gid = hdr_rb.bba.assoc_gid; + + /* + * Create the bind response struct. + */ + + init_rpc_hdr_ba(&hdr_ba, + hdr_rb.bba.max_tsize, + hdr_rb.bba.max_rsize, assoc_gid, ack_pipe_name, 0x1, 0x0, 0x0, - &(l->hdr_rb.transfer)); + &hdr_rb.transfer); + + /* + * and marshall it. + */ - smb_io_rpc_hdr_ba("", &l->hdr_ba, &l->rdata, 0); - mem_realloc_data(l->rdata.data, l->rdata.offset); + if(!smb_io_rpc_hdr_ba("", &hdr_ba, &out_hdr_ba, 0)) { + DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_BA failed.\n")); + goto err_exit; + } - /***/ - /*** now the authentication ***/ - /***/ + /* + * Now the authentication. + */ - if (l->ntlmssp_auth) - { - uint8 challenge[8]; - generate_random_buffer(challenge, 8, False); + if (p->ntlmssp_auth_requested) { + RPC_AUTH_VERIFIER auth_verifier; + RPC_AUTH_NTLMSSP_CHAL ntlmssp_chal; - /*** authentication info ***/ + generate_random_buffer(p->challenge, 8, False); - make_rpc_hdr_auth(&l->auth_info, 0x0a, 0x06, 0, 1); - smb_io_rpc_hdr_auth("", &l->auth_info, &l->rverf, 0); - mem_realloc_data(l->rverf.data, l->rverf.offset); + /*** Authentication info ***/ + + init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, NTLMSSP_AUTH_LEVEL, RPC_HDR_AUTH_LEN, 1); + if(!smb_io_rpc_hdr_auth("", &auth_info, &out_auth, 0)) { + DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_AUTH failed.\n")); + goto err_exit; + } /*** NTLMSSP verifier ***/ - make_rpc_auth_ntlmssp_verifier(&l->auth_verifier, - "NTLMSSP", NTLMSSP_CHALLENGE); - smb_io_rpc_auth_ntlmssp_verifier("", &l->auth_verifier, &l->rauth, 0); - mem_realloc_data(l->rauth.data, l->rauth.offset); + init_rpc_auth_verifier(&auth_verifier, "NTLMSSP", NTLMSSP_CHALLENGE); + if(!smb_io_rpc_auth_verifier("", &auth_verifier, &out_auth, 0)) { + DEBUG(0,("api_pipe_bind_req: marshalling of RPC_AUTH_VERIFIER failed.\n")); + goto err_exit; + } /* NTLMSSP challenge ***/ - make_rpc_auth_ntlmssp_chal(&l->ntlmssp_chal, - 0x000082b1, challenge); - smb_io_rpc_auth_ntlmssp_chal("", &l->ntlmssp_chal, &l->rntlm, 0); - mem_realloc_data(l->rntlm.data, l->rntlm.offset); - } + init_rpc_auth_ntlmssp_chal(&ntlmssp_chal, p->ntlmssp_chal_flags, p->challenge); + if(!smb_io_rpc_auth_ntlmssp_chal("", &ntlmssp_chal, &out_auth, 0)) { + DEBUG(0,("api_pipe_bind_req: marshalling of RPC_AUTH_NTLMSSP_CHAL failed.\n")); + goto err_exit; + } - /***/ - /*** then do the header, now we know the length ***/ - /***/ + /* Auth len in the rpc header doesn't include auth_header. */ + auth_len = prs_offset(&out_auth) - RPC_HDR_AUTH_LEN; + } - make_rpc_hdr(&l->hdr, pkt_type, RPC_FLG_FIRST | RPC_FLG_LAST, - l->hdr.call_id, - l->rdata.offset + l->rverf.offset + l->rauth.offset + l->rntlm.offset + 0x10, - l->rauth.offset + l->rntlm.offset); + /* + * Create the header, now we know the length. + */ - smb_io_rpc_hdr("", &l->hdr, &l->rhdr, 0); - mem_realloc_data(l->rhdr.data, l->rdata.offset); + init_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST, + p->hdr.call_id, + RPC_HEADER_LEN + prs_offset(&out_hdr_ba) + prs_offset(&out_auth), + auth_len); - /***/ - /*** link rpc header, bind acknowledgment and authentication responses ***/ - /***/ + /* + * Marshall the header into the outgoing PDU. + */ - if (l->ntlmssp_auth) - { - prs_link(NULL , &l->rhdr , &l->rdata); - prs_link(&l->rhdr , &l->rdata, &l->rverf); - prs_link(&l->rdata, &l->rverf, &l->rauth); - prs_link(&l->rverf, &l->rauth, &l->rntlm); - prs_link(&l->rauth, &l->rntlm, NULL ); + if(!smb_io_rpc_hdr("", &p->hdr, &outgoing_rpc, 0)) { + DEBUG(0,("pi_pipe_bind_req: marshalling of RPC_HDR failed.\n")); + goto err_exit; } - else - { - prs_link(NULL , &l->rhdr , &l->rdata); - prs_link(&l->rhdr, &l->rdata, NULL ); + + /* + * Now add the RPC_HDR_BA and any auth needed. + */ + + if(!prs_append_prs_data( &outgoing_rpc, &out_hdr_ba)) { + DEBUG(0,("api_pipe_bind_req: append of RPC_HDR_BA failed.\n")); + goto err_exit; } - return True; -} + if(p->ntlmssp_auth_requested && !prs_append_prs_data( &outgoing_rpc, &out_auth)) { + DEBUG(0,("api_pipe_bind_req: append of auth info failed.\n")); + goto err_exit; + } -static BOOL api_pipe_bind_and_alt_req(rpcsrv_struct *l, prs_struct *pd, - const char* name, - enum RPC_PKT_TYPE pkt_type) -{ - fstring ack_pipe_name; - fstring pipe_srv_name; - int i = 0; + /* + * Setup the lengths for the initial reply. + */ - DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__)); + p->data_sent_length = 0; + p->current_pdu_len = prs_offset(&outgoing_rpc); + p->current_pdu_sent = 0; - for (i = 0; i < num_cmds; i++) - { - if (strequal(api_fd_commands[i]->pipe_clnt_name, name) && - api_fd_commands[i]->fn != NULL) - { - DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", - api_fd_commands[i]->pipe_clnt_name, - api_fd_commands[i]->pipe_srv_name)); - fstrcpy(pipe_srv_name, api_fd_commands[i]->pipe_srv_name); - break; - } - } + prs_mem_free(&out_hdr_ba); + prs_mem_free(&out_auth); - if (api_fd_commands[i]->fn == NULL) return False; + return True; - switch (pkt_type) - { - case RPC_BINDACK: - { - /* name has to be \PIPE\xxxxx */ - fstrcpy(ack_pipe_name, "\\PIPE\\"); - fstrcat(ack_pipe_name, pipe_srv_name); - break; - } - case RPC_ALTCONTRESP: - { - /* secondary address CAN be NULL - * as the specs says it's ignored. - * It MUST NULL to have the spoolss working. - */ - fstrcpy(ack_pipe_name, ""); - break; - } - default: - { - return False; - } - } - return srv_pipe_bind_and_alt_req(l, pd, ack_pipe_name, pkt_type); -} + err_exit: -/* - * The RPC Alter-Context call is used only by the spoolss pipe - * simply because there is a bug (?) in the MS unmarshalling code - * or in the marshalling code. If it's in the later, then Samba - * have the same bug. - */ -static BOOL api_pipe_bind_req(rpcsrv_struct *l, prs_struct *pd, - const char* name) -{ - return api_pipe_bind_and_alt_req(l, pd, name, RPC_BINDACK); + prs_mem_free(&out_hdr_ba); + prs_mem_free(&out_auth); + return False; } -static BOOL api_pipe_alt_req(rpcsrv_struct *l, prs_struct *pd, - const char* name) -{ - return api_pipe_bind_and_alt_req(l, pd, name, RPC_ALTCONTRESP); -} +/**************************************************************************** + Deal with sign & seal processing on an RPC request. +****************************************************************************/ -static BOOL api_pipe_auth_process(rpcsrv_struct *l, prs_struct *pd) +static BOOL api_pipe_auth_process(pipes_struct *p, prs_struct *rpc_in) { - BOOL auth_verify = IS_BITS_SET_ALL(l->ntlmssp_chal.neg_flags, NTLMSSP_NEGOTIATE_SIGN); - BOOL auth_seal = IS_BITS_SET_ALL(l->ntlmssp_chal.neg_flags, NTLMSSP_NEGOTIATE_SEAL); + /* + * We always negotiate the following two bits.... + */ + BOOL auth_verify = IS_BITS_SET_ALL(p->ntlmssp_chal_flags, NTLMSSP_NEGOTIATE_SIGN); + BOOL auth_seal = IS_BITS_SET_ALL(p->ntlmssp_chal_flags, NTLMSSP_NEGOTIATE_SEAL); int data_len; int auth_len; uint32 old_offset; uint32 crc32 = 0; - auth_len = l->hdr.auth_len; + auth_len = p->hdr.auth_len; - if (auth_len != 16 && auth_verify) - { + if ((auth_len != RPC_AUTH_NTLMSSP_CHK_LEN) && auth_verify) { + DEBUG(0,("api_pipe_auth_process: Incorrect auth_len %d.\n", auth_len )); return False; } - data_len = l->hdr.frag_len - auth_len - (auth_verify ? 8 : 0) - 0x18; + /* + * The following is that length of the data we must verify or unseal. + * This doesn't include the RPC headers or the auth_len or the RPC_HDR_AUTH_LEN + * preceeding the auth_data. + */ + + data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - + (auth_verify ? RPC_HDR_AUTH_LEN : 0) - auth_len; DEBUG(5,("api_pipe_auth_process: sign: %s seal: %s data %d auth %d\n", BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len, auth_len)); - if (auth_seal) - { - char *data = mem_data(&pd->data, pd->offset); - DEBUG(5,("api_pipe_auth_process: data %d\n", pd->offset)); - NTLMSSPcalc_p(l, (uchar*)data, data_len); - crc32 = crc32_calc_buffer(data_len, data); + if (auth_seal) { + char *data = prs_data_p(rpc_in) + RPC_HEADER_LEN + RPC_HDR_REQ_LEN; + NTLMSSPcalc_p(p, (uchar*)data, data_len); + crc32 = crc32_calc_buffer(data, data_len); } - /*** skip the data, record the offset so we can restore it again */ - old_offset = pd->offset; + old_offset = prs_offset(rpc_in); - if (auth_seal || auth_verify) - { - pd->offset += data_len; - smb_io_rpc_hdr_auth("hdr_auth", &l->auth_info, pd, 0); - } + if (auth_seal || auth_verify) { + RPC_HDR_AUTH auth_info; - if (auth_verify) - { - char *req_data = mem_data(&pd->data, pd->offset + 4); - DEBUG(5,("api_pipe_auth_process: auth %d\n", pd->offset + 4)); - NTLMSSPcalc_p(l, (uchar*)req_data, 12); - smb_io_rpc_auth_ntlmssp_chk("auth_sign", &(l->ntlmssp_chk), pd, 0); + if(!prs_set_offset(rpc_in, old_offset + data_len)) { + DEBUG(0,("api_pipe_auth_process: cannot move offset to %u.\n", + (unsigned int)old_offset + data_len )); + return False; + } - if (!rpc_auth_ntlmssp_chk(&(l->ntlmssp_chk), crc32, - l->ntlmssp_seq_num)) - { + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, rpc_in, 0)) { + DEBUG(0,("api_pipe_auth_process: failed to unmarshall RPC_HDR_AUTH.\n")); return False; } } - pd->offset = old_offset; - - return True; -} - -static BOOL api_pipe_request(rpcsrv_struct *l, prs_struct *pd, const char* name) -{ - int i = 0; - - if (l->ntlmssp_auth && l->ntlmssp_validated) - { - if (!api_pipe_auth_process(l, pd)) return False; + if (auth_verify) { + RPC_AUTH_NTLMSSP_CHK ntlmssp_chk; + char *req_data = prs_data_p(rpc_in) + prs_offset(rpc_in) + 4; - DEBUG(0,("api_pipe_request: **** MUST CALL become_user() HERE **** \n")); -#if 0 - become_user(); -#endif - } + DEBUG(5,("api_pipe_auth_process: auth %d\n", prs_offset(rpc_in) + 4)); - for (i = 0; i < num_cmds; i++) - { - if (strequal(api_fd_commands[i]->pipe_clnt_name, name) && - api_fd_commands[i]->fn != NULL) - { - DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i]->pipe_clnt_name)); - return api_fd_commands[i]->fn(l, pd); + /* + * Ensure we have RPC_AUTH_NTLMSSP_CHK_LEN - 4 more bytes in the + * incoming buffer. + */ + if(prs_mem_get(rpc_in, RPC_AUTH_NTLMSSP_CHK_LEN - 4) == NULL) { + DEBUG(0,("api_pipe_auth_process: missing %d bytes in buffer.\n", + RPC_AUTH_NTLMSSP_CHK_LEN - 4 )); + return False; } - } - return False; -} - -BOOL rpc_add_to_pdu(prs_struct *ps, const char *data, int len) -{ - int prev_size; - int new_size; - char *to = NULL; - - ps->offset = 0; - if (ps->data == NULL) - { - DEBUG(10,("rpc_add_to_pdu: new_size: %d\n", len)); - prs_init(ps, len, 4, 0, True); - prev_size = 0; - new_size = len; - if (ps->data == NULL) - { + NTLMSSPcalc_p(p, (uchar*)req_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4); + if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, rpc_in, 0)) { + DEBUG(0,("api_pipe_auth_process: failed to unmarshall RPC_AUTH_NTLMSSP_CHK.\n")); return False; } - } - else - { - prev_size = ps->data->data_used; - new_size = prev_size + len; - DEBUG(10,("rpc_add_to_pdu: prev_size: %d new_size: %d\n", - prev_size, new_size)); - if (!mem_realloc_data(ps->data, new_size)) - { + + if (!rpc_auth_ntlmssp_chk(&ntlmssp_chk, crc32, p->ntlmssp_seq_num)) { + DEBUG(0,("api_pipe_auth_process: NTLMSSP check failed.\n")); return False; } } - DEBUG(10,("ps->data->start: %d\n", ps->data->offset.start)); - ps->data->offset.start = 0x0; + /* + * Return the current pointer to the data offset. + */ - to = mem_data(&ps->data, prev_size); - if (to == NULL) - { - DEBUG(10,("rpc_add_to_pdu: data could not be found\n")); - return False; - } - if (ps->data->data_used != new_size) - { - DEBUG(10,("rpc_add_to_pdu: ERROR: data used %d new_size %d\n", - ps->data->data_used, new_size)); + if(!prs_set_offset(rpc_in, old_offset)) { + DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n", + (unsigned int)old_offset )); return False; } - memcpy(to, data, len); + return True; } -static BOOL rpc_redir_remote(pipes_struct *p, prs_struct *req, prs_struct *resp) +/**************************************************************************** + Find the correct RPC function to call for this request. + If the pipe is authenticated then become the correct UNIX user + before doing the call. +****************************************************************************/ + +static BOOL api_pipe_request(pipes_struct *p, prs_struct *rpc_in) { - DEBUG(10,("rpc_redirect\n")); + int i = 0; + BOOL ret = False; + BOOL changed_user_id = False; - if (!msrpc_send_prs(p->m, req)) - { - DEBUG(2,("msrpc redirect send failed\n")); - return False; + if (p->ntlmssp_auth_validated) { + if (!api_pipe_auth_process(p, rpc_in)) + return False; + + if(!become_authenticated_pipe_user(p)) + return False; + + changed_user_id = True; } - if (!msrpc_receive_prs(p->m, resp)) - { - DEBUG(2,("msrpc redirect receive failed\n")); - return False; + + for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) { + if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) && + api_fd_commands[i].fn != NULL) { + DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name)); + ret = api_fd_commands[i].fn(p, rpc_in); + } } - prs_link(NULL, resp, NULL); - prs_debug_out(resp, "redirect", 100); - return True; + + if(changed_user_id) + unbecome_authenticated_pipe_user(p); + + return ret; } -static BOOL rpc_redir_local(rpcsrv_struct *l, prs_struct *req, prs_struct *resp, - const char* name) +/**************************************************************************** + This function is the entry point to processing a DCE/RPC request. + All the data for the request (including RPC headers and authentication + verifiers) must be linearized in the input_data buffer, with a length + of data_len. + + The output is placed into the pipes_struct, and handed back to the + client on demand. +****************************************************************************/ + +BOOL rpc_command(pipes_struct *p, char *input_data, int data_len) { + prs_struct rpc_in; BOOL reply = False; - if (req->data == NULL) return False; + if (input_data == NULL) + return False; + + prs_init(&rpc_in, 0, 4, UNMARSHALL); - /* lkclXXXX still assume that the first complete PDU is always - in a single request!!! + /* + * Hand the data to the prs_struct, but don't let + * it own it. */ - /* process the rpc header */ - req->offset = 0x0; - smb_io_rpc_hdr("", &l->hdr, req, 0); + prs_give_memory( &rpc_in, input_data, (uint32)data_len, False); - if (req->offset == 0) return False; + /* Unmarshall the rpc header */ + if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) { + DEBUG(0,("rpc_command: failed to unmarshall RPC_HDR.\n")); + return False; + } - switch (l->hdr.pkt_type) - { - case RPC_BIND : - { - reply = api_pipe_bind_req(l, req, name); - break; - } - case RPC_ALTCONT: - { - reply = api_pipe_alt_req(l, req, name); - break; - } - case RPC_REQUEST: - { - if (l->ntlmssp_auth && !l->ntlmssp_validated) - { - /* authentication _was_ requested - and it failed. sorry, no deal! - */ - reply = False; - } - else - { - /* read the rpc header */ - smb_io_rpc_hdr_req("req", &(l->hdr_req), req, 0); - reply = api_pipe_request(l, req, name); + /* + * Create the response data buffer. + */ + + if(!pipe_init_outgoing_data(p)) { + DEBUG(0,("rpc_command: failed to unmarshall RPC_HDR.\n")); + return False; + } + + switch (p->hdr.pkt_type) { + case RPC_BIND: + reply = api_pipe_bind_req(p, &rpc_in); + break; + case RPC_REQUEST: + if (p->ntlmssp_auth_requested && !p->ntlmssp_auth_validated) { + /* authentication _was_ requested + and it failed. sorry, no deal! + */ + DEBUG(0,("rpc_command: RPC request received on pipe %s where \ +authentication failed. Denying the request.\n", p->name)); + reply = False; + } else { + /* read the RPC request header */ + if(!smb_io_rpc_hdr_req("req", &p->hdr_req, &rpc_in, 0)) { + DEBUG(0,("rpc_command: failed to unmarshall RPC_HDR_REQ.\n")); + return False; } - break; - } - case RPC_BINDRESP: /* not the real name! */ - { - reply = api_pipe_bind_auth_resp(l, req); - l->ntlmssp_auth = reply; - break; + reply = api_pipe_request(p, &rpc_in); } + break; + case RPC_BINDRESP: /* not the real name! */ + reply = api_pipe_bind_auth_resp(p, &rpc_in); + break; } if (!reply) - { - reply = api_pipe_fault_resp(l, req, 0x1c010002); - } - - if (reply) - { - /* flatten the data into a single pdu */ - reply = prs_copy(resp, &l->rhdr); - } - - /* delete intermediate data used to set up the pdu. leave - rdata alone because that's got the rest of the data in it */ - rpcsrv_free_temp(l); + DEBUG(3,("rpc_command: DCE/RPC fault should be sent here\n")); return reply; } -BOOL rpc_send_and_rcv_pdu(pipes_struct *p) -{ - DEBUG(10,("rpc_send_and_rcv_pdu\n")); - - if (p->m != NULL) - { - return rpc_redir_remote(p, &p->smb_pdu, &p->rsmb_pdu); - } - else if (p->l != NULL) - { - return rpc_redir_local(p->l, &p->smb_pdu, &p->rsmb_pdu, - p->name); - } - return False; -} /******************************************************************* - entry point from msrpc to smb. adds data received to pdu; checks - pdu; hands pdu off to msrpc, which gets a pdu back (except in the - case of the RPC_BINDCONT pdu). + Calls the underlying RPC function for a named pipe. ********************************************************************/ -BOOL rpc_to_smb(pipes_struct *p, char *data, int len) -{ - BOOL reply = rpc_add_to_pdu(&p->smb_pdu, data, len); - if (reply && is_complete_pdu(&p->smb_pdu)) - { - p->smb_pdu.offset = p->smb_pdu.data->data_size; - prs_link(NULL, &p->smb_pdu, NULL); - reply = rpc_send_and_rcv_pdu(p); - mem_free_data(p->smb_pdu.data); - prs_init(&p->smb_pdu, 0, 4, 0, True); - - } - return reply; -} - -/******************************************************************* - receives a netlogon pipe and responds. - ********************************************************************/ -static BOOL api_rpc_command(rpcsrv_struct *l, - char *rpc_name, struct api_struct *api_rpc_cmds, - prs_struct *data) +BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds, + prs_struct *rpc_in) { int fn_num; - DEBUG(4,("api_rpc_command: %s op 0x%x - ", rpc_name, l->hdr_req.opnum)); - for (fn_num = 0; api_rpc_cmds[fn_num].name; fn_num++) - { - if (api_rpc_cmds[fn_num].opnum == l->hdr_req.opnum && api_rpc_cmds[fn_num].fn != NULL) - { + /* interpret the command */ + DEBUG(4,("api_rpcTNP: %s op 0x%x - ", rpc_name, p->hdr_req.opnum)); + + for (fn_num = 0; api_rpc_cmds[fn_num].name; fn_num++) { + if (api_rpc_cmds[fn_num].opnum == p->hdr_req.opnum && api_rpc_cmds[fn_num].fn != NULL) { DEBUG(3,("api_rpc_command: %s\n", api_rpc_cmds[fn_num].name)); break; } } - if (api_rpc_cmds[fn_num].name == NULL) - { + if (api_rpc_cmds[fn_num].name == NULL) { DEBUG(4, ("unknown\n")); return False; } - /* start off with 1024 bytes, and a large safety margin too */ - prs_init(&l->rdata, 1024, 4, SAFETY_MARGIN, False); - /* do the actual command */ - api_rpc_cmds[fn_num].fn(l, data, &(l->rdata)); - - if (l->rdata.data == NULL || l->rdata.offset == 0) - { - mem_free_data(l->rdata.data); + if(!api_rpc_cmds[fn_num].fn(p->vuid, rpc_in, &p->rdata)) { + DEBUG(0,("api_rpcTNP: %s: failed.\n", rpc_name)); + prs_mem_free(&p->rdata); return False; } - mem_realloc_data(l->rdata.data, l->rdata.offset); - - DEBUG(10,("called %s\n", rpc_name)); + DEBUG(5,("api_rpcTNP: called %s successfully\n", rpc_name)); return True; } - - -/******************************************************************* - receives a netlogon pipe and responds. - ********************************************************************/ -BOOL api_rpcTNP(rpcsrv_struct *l, char *rpc_name, struct api_struct *api_rpc_cmds, - prs_struct *data) -{ - if (data == NULL || data->data == NULL) - { - DEBUG(2,("%s: NULL data received\n", rpc_name)); - return False; - } - - /* interpret the command */ - if (!api_rpc_command(l, rpc_name, api_rpc_cmds, data)) - { - return False; - } - - /* create the rpc header */ - if (!create_rpc_reply(l, 0)) - { - return False; - } - - return True; -} - -BOOL is_complete_pdu(prs_struct *ps) -{ - RPC_HDR hdr; - int len = ps->data->data_size; - - DEBUG(10,("is_complete_pdu - len %d\n", len)); - ps->offset = 0x0; - - if (!ps->io) - { - /* writing. oops!! */ - DEBUG(4,("is_complete_pdu: write set, not read!\n")); - return False; - } - - if (!smb_io_rpc_hdr("hdr", &hdr, ps, 0)) - { - return False; - } - /* check that the fragment length is equal to the data length so far */ - return hdr.frag_len == len; -} diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index f8bde1bf9b..b21b768a6e 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -5,6 +5,7 @@ * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-1998, * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Jeremy Allison 1999. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -55,7 +56,7 @@ void set_pipe_handle_offset(int max_open_files) } /**************************************************************************** - reset pipe chain handle number + Reset pipe chain handle number. ****************************************************************************/ void reset_chain_p(void) { @@ -63,63 +64,64 @@ void reset_chain_p(void) } /**************************************************************************** - initialise pipe handle states... + Initialise pipe handle states. ****************************************************************************/ + void init_rpc_pipe_hnd(void) { bmap = bitmap_allocate(MAX_OPEN_PIPES); - if (!bmap) { + if (!bmap) exit_server("out of memory in init_rpc_pipe_hnd\n"); - } } +/**************************************************************************** + Initialise an outgoing packet. +****************************************************************************/ + +BOOL pipe_init_outgoing_data( pipes_struct *p) +{ + + memset(p->current_pdu, '\0', sizeof(p->current_pdu)); + + /* Free any memory in the current return data buffer. */ + prs_mem_free(&p->rdata); + + /* + * Initialize the outgoing RPC data buffer. + * we will use this as the raw data area for replying to rpc requests. + */ + if(!prs_init(&p->rdata, 1024, 4, MARSHALL)) { + DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n")); + return False; + } + + /* Reset the offset counters. */ + p->data_sent_length = 0; + p->current_pdu_len = 0; + p->current_pdu_sent = 0; + + return True; +} /**************************************************************************** - find first available file slot + Find first available pipe slot. ****************************************************************************/ + pipes_struct *open_rpc_pipe_p(char *pipe_name, connection_struct *conn, uint16 vuid) { int i; pipes_struct *p; static int next_pipe; - struct msrpc_state *m = NULL; - struct rpcsrv_struct *l = NULL; - user_struct *vuser = get_valid_user_struct(vuid); - struct user_creds usr; - - ZERO_STRUCT(usr); DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n", pipe_name, pipes_open)); - if (vuser == NULL) - { - DEBUG(4,("invalid vuid %d\n", vuid)); - return NULL; - } - - /* set up unix credentials from the smb side, to feed over the pipe */ - make_creds_unix(&usr.uxc, vuser->name, vuser->requested_name, - vuser->real_name, vuser->guest); - usr.ptr_uxc = 1; - make_creds_unix_sec(&usr.uxs, vuser->uid, vuser->gid, - vuser->n_groups, vuser->groups); - usr.ptr_uxs = 1; - - /* set up nt credentials from the smb side, to feed over the pipe */ - /* lkclXXXX todo! - make_creds_nt(&usr.ntc); - make_creds_nt_sec(&usr.nts); - */ - /* not repeating pipe numbers makes it easier to track things in log files and prevents client bugs where pipe numbers are reused over connection restarts */ if (next_pipe == 0) - { next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES; - } i = bitmap_find(bmap, next_pipe); @@ -131,44 +133,19 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name, next_pipe = (i+1) % MAX_OPEN_PIPES; for (p = Pipes; p; p = p->next) - { DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum)); - } - - m = msrpc_use_add(pipe_name, &usr, False); - if (m == NULL) - { - DEBUG(5,("open pipes: msrpc redirect failed\n")); - return NULL; - } -#if 0 - } - else - { - l = malloc(sizeof(*l)); - if (l == NULL) - { - DEBUG(5,("open pipes: local msrpc malloc failed\n")); - return NULL; - } - ZERO_STRUCTP(l); - l->rhdr.data = NULL; - l->rdata.data = NULL; - l->rhdr.offset = 0; - l->rdata.offset = 0; - - l->ntlmssp_validated = False; - l->ntlmssp_auth = False; - - memcpy(l->user_sess_key, vuser->user_sess_key, - sizeof(l->user_sess_key)); - } -#endif p = (pipes_struct *)malloc(sizeof(*p)); - if (!p) return NULL; + if (!p) + return NULL; ZERO_STRUCTP(p); + + /* + * Initialize the RPC and PDU data buffers with no memory. + */ + prs_init(&p->rdata, 0, 4, MARSHALL); + DLIST_ADD(Pipes, p); bitmap_set(bmap, i); @@ -177,24 +154,28 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name, pipes_open++; p->pnum = i; - p->m = m; - p->l = l; p->open = True; p->device_state = 0; p->priority = 0; p->conn = conn; p->vuid = vuid; + + p->max_trans_reply = 0; - p->file_offset = 0; - p->prev_pdu_file_offset = 0; - p->hdr_offsets = 0; - - fstrcpy(p->name, pipe_name); + p->ntlmssp_chal_flags = 0; + p->ntlmssp_auth_validated = False; + p->ntlmssp_auth_requested = False; - prs_init(&p->smb_pdu, 0, 4, 0, True); - prs_init(&p->rsmb_pdu, 0, 4, 0, False); + p->current_pdu_len = 0; + p->current_pdu_sent = 0; + p->data_sent_length = 0; + p->uid = (uid_t)-1; + p->gid = (gid_t)-1; + + fstrcpy(p->name, pipe_name); + DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n", pipe_name, i, pipes_open)); @@ -202,182 +183,179 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name, /* OVERWRITE p as a temp variable, to display all open pipes */ for (p = Pipes; p; p = p->next) - { DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum)); - } return chain_p; } /**************************************************************************** - writes data to a pipe. + Accepts incoming data on an rpc pipe. - SERIOUSLY ALPHA CODE! + This code is probably incorrect at the moment. The problem is + that the rpc request shouldn't really be executed until all the + data needed for it is received. This currently assumes that each + SMBwrite or SMBwriteX contains all the data needed for an rpc + request. JRA. ****************************************************************************/ -ssize_t write_pipe(pipes_struct *p, char *data, size_t n) + +ssize_t write_to_pipe(pipes_struct *p, char *data, size_t n) { DEBUG(6,("write_pipe: %x", p->pnum)); + DEBUG(6,("name: %s open: %s len: %d", - p->name, BOOLSTR(p->open), n)); + p->name, BOOLSTR(p->open), (int)n)); dump_data(50, data, n); - return rpc_to_smb(p, data, n) ? ((ssize_t)n) : -1; + return rpc_command(p, data, (int)n) ? ((ssize_t)n) : -1; } /**************************************************************************** - reads data from a pipe. + Replyies to a request to read data from a pipe. - headers are interspersed with the data at regular intervals. by the time + Headers are interspersed with the data at PDU intervals. By the time this function is called, the start of the data could possibly have been read by an SMBtrans (file_offset != 0). - calling create_rpc_reply() here is a fudge. the data should already + Calling create_rpc_reply() here is a hack. The data should already have been prepared into arrays of headers + data stream sections. ****************************************************************************/ -int read_pipe(pipes_struct *p, char *data, uint32 pos, int n) + +int read_from_pipe(pipes_struct *p, char *data, int n) { - int num = 0; - int pdu_len = 0; - uint32 hdr_num = 0; - int pdu_data_sent; /* amount of current pdu already sent */ - int data_pos; /* entire rpc data sent - no headers, no auth verifiers */ - int this_pdu_data_pos; - - DEBUG(6,("read_pipe: %x name: %s open: %s pos: %d len: %d", - p->pnum, p->name, BOOLSTR(p->open), - pos, n)); - - if (!p || !p->open) - { - DEBUG(6,("pipe not open\n")); + uint32 pdu_remaining = 0; + int data_returned = 0; + + if (!p || !p->open) { + DEBUG(0,("read_from_pipe: pipe not open\n")); return -1; } + DEBUG(6,("read_from_pipe: %x", p->pnum)); - if (p->rsmb_pdu.data == NULL || p->rsmb_pdu.data->data == NULL || - p->rsmb_pdu.data->data_used == 0) - { - return 0; + DEBUG(6,("name: %s len: %d\n", p->name, n)); + + /* + * We cannot return more than one PDU length per + * read request. + */ + + if(n > MAX_PDU_FRAG_LEN) { + DEBUG(0,("read_from_pipe: loo large read (%d) requested on pipe %s. We can \ +only service %d sized reads.\n", n, p->name, MAX_PDU_FRAG_LEN )); + return -1; } - DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n", - p, p->file_offset, n)); + /* + * Determine if there is still data to send in the + * pipe PDU buffer. Always send this first. Never + * send more than is left in the current PDU. The + * client should send a new read request for a new + * PDU. + */ - /* the read request starts from where the SMBtrans2 left off. */ - data_pos = p->file_offset - p->hdr_offsets; - pdu_data_sent = p->file_offset - p->prev_pdu_file_offset; - this_pdu_data_pos = (pdu_data_sent == 0) ? 0 : (pdu_data_sent - 0x18); + if((pdu_remaining = p->current_pdu_len - p->current_pdu_sent) > 0) { + data_returned = MIN(n, pdu_remaining); - if (!IS_BITS_SET_ALL(p->l->hdr.flags, RPC_FLG_LAST)) - { - /* intermediate fragment - possibility of another header */ - - DEBUG(5,("read_pipe: frag_len: %d data_pos: %d pdu_data_sent: %d\n", - p->l->hdr.frag_len, data_pos, pdu_data_sent)); - - if (pdu_data_sent == 0) - { - DEBUG(6,("read_pipe: next fragment header\n")); - - /* this is subtracted from the total data bytes, later */ - hdr_num = 0x18; - p->hdr_offsets += 0x18; - data_pos -= 0x18; - - /* create and copy in a new header. */ - create_rpc_reply(p->l, data_pos); - } - } - - pdu_len = mem_buf_len(p->rsmb_pdu.data); - num = pdu_len - this_pdu_data_pos; - - DEBUG(6,("read_pipe: pdu_len: %d num: %d n: %d\n", pdu_len, num, n)); - - if (num > n) num = n; - if (num <= 0) - { - DEBUG(5,("read_pipe: 0 or -ve data length\n")); - return 0; - } + DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, current_pdu_sent = %u \ +returning %d bytes.\n", p->name, (unsigned int)p->current_pdu_len, + (unsigned int)p->current_pdu_sent, (int)data_returned)); - if (num < hdr_num) - { - DEBUG(5,("read_pipe: warning - data read only part of a header\n")); + memcpy( data, &p->current_pdu[p->current_pdu_sent], (size_t)data_returned); + p->current_pdu_sent += (uint32)data_returned; + return data_returned; } - mem_buf_copy(data, p->rsmb_pdu.data, pdu_data_sent, num); - - p->file_offset += num; - pdu_data_sent += num; - - if (hdr_num == 0x18 && num == 0x18) - { - DEBUG(6,("read_pipe: just header read\n")); + /* + * At this point p->current_pdu_len == p->current_pdu_sent (which + * may of course be zero if this is the first return fragment. + */ + + DEBUG(10,("read_from_pipe: %s: data_sent_length = %u, prs_offset(&p->rdata) = %u.\n", + p->name, (unsigned int)p->data_sent_length, (unsigned int)prs_offset(&p->rdata) )); + + if(p->data_sent_length >= prs_offset(&p->rdata)) { + /* + * We have sent all possible data. Return 0. + */ + return 0; } - if (pdu_data_sent == p->l->hdr.frag_len) - { - DEBUG(6,("read_pipe: next fragment expected\n")); - p->prev_pdu_file_offset = p->file_offset; + /* + * We need to create a new PDU from the data left in p->rdata. + * Create the header/data/footers. This also sets up the fields + * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length + * and stores the outgoing PDU in p->current_pdu. + */ + + if(!create_next_pdu(p)) { + DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", + p->name)); + return -1; } - return num; -} + data_returned = MIN(n, p->current_pdu_len); + memcpy( data, p->current_pdu, (size_t)data_returned); + p->current_pdu_sent += (uint32)data_returned; + return data_returned; +} /**************************************************************************** - wait device state on a pipe. exactly what this is for is unknown... + Wait device state on a pipe. Exactly what this is for is unknown... ****************************************************************************/ + BOOL wait_rpc_pipe_hnd_state(pipes_struct *p, uint16 priority) { - if (p == NULL) return False; + if (p == NULL) + return False; - if (p->open) - { - DEBUG(3,("%s Setting pipe wait state priority=%x on pipe (name=%s)\n", - timestring(), priority, p->name)); + if (p->open) { + DEBUG(3,("wait_rpc_pipe_hnd_state: Setting pipe wait state priority=%x on pipe (name=%s)\n", + priority, p->name)); p->priority = priority; return True; } - DEBUG(3,("%s Error setting pipe wait state priority=%x (name=%s)\n", - timestring(), priority, p->name)); + DEBUG(3,("wait_rpc_pipe_hnd_state: Error setting pipe wait state priority=%x (name=%s)\n", + priority, p->name)); return False; } /**************************************************************************** - set device state on a pipe. exactly what this is for is unknown... + Set device state on a pipe. Exactly what this is for is unknown... ****************************************************************************/ + BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state) { - if (p == NULL) return False; + if (p == NULL) + return False; if (p->open) { - DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s)\n", - timestring(), device_state, p->name)); + DEBUG(3,("set_rpc_pipe_hnd_state: Setting pipe device state=%x on pipe (name=%s)\n", + device_state, p->name)); p->device_state = device_state; return True; } - DEBUG(3,("%s Error setting pipe device state=%x (name=%s)\n", - timestring(), device_state, p->name)); + DEBUG(3,("set_rpc_pipe_hnd_state: Error setting pipe device state=%x (name=%s)\n", + device_state, p->name)); return False; } /**************************************************************************** - close an rpc pipe + Close an rpc pipe. ****************************************************************************/ + BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn) { if (!p) { @@ -385,8 +363,7 @@ BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn) return False; } - mem_buf_free(&(p->smb_pdu .data)); - mem_buf_free(&(p->rsmb_pdu.data)); + prs_mem_free(&p->rdata); bitmap_clear(bmap, p->pnum - pipe_handle_offset); @@ -397,50 +374,31 @@ BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn) DLIST_REMOVE(Pipes, p); - if (p->m != NULL) - { - DEBUG(4,("closed msrpc redirect: ")); - if (msrpc_use_del(p->m->pipe_name, &p->m->usr, False, NULL)) - { - DEBUG(4,("OK\n")); - } - else - { - DEBUG(4,("FAILED\n")); - } - } - - if (p->l != NULL) - { - DEBUG(4,("closed msrpc local: OK\n")); - - mem_free_data(p->l->rdata .data); - rpcsrv_free_temp(p->l); - - free(p->l); - } - ZERO_STRUCTP(p); + free(p); return True; } /**************************************************************************** - close an rpc pipe + Find an rpc pipe given a pipe handle in a buffer and an offset. ****************************************************************************/ + pipes_struct *get_rpc_pipe_p(char *buf, int where) { int pnum = SVAL(buf,where); - if (chain_p) return chain_p; + if (chain_p) + return chain_p; return get_rpc_pipe(pnum); } /**************************************************************************** - close an rpc pipe + Find an rpc pipe given a pipe handle. ****************************************************************************/ + pipes_struct *get_rpc_pipe(int pnum) { pipes_struct *p; @@ -448,15 +406,11 @@ pipes_struct *get_rpc_pipe(int pnum) DEBUG(4,("search for pipe pnum=%x\n", pnum)); for (p=Pipes;p;p=p->next) - { DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", p->name, p->pnum, pipes_open)); - } - for (p=Pipes;p;p=p->next) - { - if (p->pnum == pnum) - { + for (p=Pipes;p;p=p->next) { + if (p->pnum == pnum) { chain_p = p; return p; } @@ -464,4 +418,3 @@ pipes_struct *get_rpc_pipe(int pnum) return NULL; } - diff --git a/source3/rpc_server/srv_reg.c b/source3/rpc_server/srv_reg.c index ea3150fd3c..fc3ce9c0d2 100644 --- a/source3/rpc_server/srv_reg.c +++ b/source3/rpc_server/srv_reg.c @@ -1,4 +1,3 @@ - /* * Unix SMB/Netbios implementation. * Version 1.9. @@ -38,10 +37,10 @@ static void reg_reply_close(REG_Q_CLOSE *q_r, REG_R_CLOSE r_u; /* set up the REG unknown_1 response */ - bzero(r_u.pol.data, POL_HND_SIZE); + memset((char *)r_u.pol.data, '\0', POL_HND_SIZE); /* close the policy handle */ - if (close_policy_hnd(&(q_r->pol))) + if (close_lsa_policy_hnd(&(q_r->pol))) { r_u.status = 0; } @@ -61,7 +60,7 @@ static void reg_reply_close(REG_Q_CLOSE *q_r, /******************************************************************* api_reg_close ********************************************************************/ -static void api_reg_close( rpcsrv_struct *p, prs_struct *data, +static BOOL api_reg_close( uint16 vuid, prs_struct *data, prs_struct *rdata ) { REG_Q_CLOSE q_r; @@ -71,6 +70,8 @@ static void api_reg_close( rpcsrv_struct *p, prs_struct *data, /* construct reply. always indicate success */ reg_reply_close(&q_r, rdata); + + return True; } @@ -84,7 +85,7 @@ static void reg_reply_open(REG_Q_OPEN_HKLM *q_r, r_u.status = 0x0; /* get a (unique) handle. open a policy on it. */ - if (r_u.status == 0x0 && !open_policy_hnd(&(r_u.pol))) + if (r_u.status == 0x0 && !open_lsa_policy_hnd(&(r_u.pol))) { r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -100,7 +101,7 @@ static void reg_reply_open(REG_Q_OPEN_HKLM *q_r, /******************************************************************* api_reg_open ********************************************************************/ -static void api_reg_open( rpcsrv_struct *p, prs_struct *data, +static BOOL api_reg_open( uint16 vuid, prs_struct *data, prs_struct *rdata ) { REG_Q_OPEN_HKLM q_u; @@ -110,6 +111,8 @@ static void api_reg_open( rpcsrv_struct *p, prs_struct *data, /* construct reply. always indicate success */ reg_reply_open(&q_u, rdata); + + return True; } @@ -126,35 +129,30 @@ static void reg_reply_open_entry(REG_Q_OPEN_ENTRY *q_u, DEBUG(5,("reg_open_entry: %d\n", __LINE__)); - if (status == 0 && find_policy_by_hnd(&(q_u->pol)) == -1) + if (status == 0 && find_lsa_policy_by_hnd(&(q_u->pol)) == -1) { status = 0xC000000 | NT_STATUS_INVALID_HANDLE; } - if (status == 0x0 && !open_policy_hnd(&pol)) + if (status == 0x0 && !open_lsa_policy_hnd(&pol)) { status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */ } - unistr2_to_ascii(name, &q_u->uni_name, sizeof(name)-1); + fstrcpy(name, dos_unistrn2(q_u->uni_name.buffer, q_u->uni_name.uni_str_len)); if (status == 0x0) { DEBUG(5,("reg_open_entry: %s\n", name)); /* lkcl XXXX do a check on the name, here */ - if (!strequal(name, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions") && - !strequal(name, "SYSTEM\\CurrentControlSet\\Services\\NETLOGON\\Parameters\\")) - { - status = 0xC000000 | NT_STATUS_ACCESS_DENIED; - } } - if (status == 0x0 && !set_policy_reg_name(&pol, name)) + if (status == 0x0 && !set_lsa_policy_reg_name(&pol, name)) { status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */ } - make_reg_r_open_entry(&r_u, &pol, status); + init_reg_r_open_entry(&r_u, &pol, status); /* store the response in the SMB stream */ reg_io_r_open_entry("", &r_u, rdata, 0); @@ -165,7 +163,7 @@ static void reg_reply_open_entry(REG_Q_OPEN_ENTRY *q_u, /******************************************************************* api_reg_open_entry ********************************************************************/ -static void api_reg_open_entry( rpcsrv_struct *p, prs_struct *data, +static BOOL api_reg_open_entry( uint16 vuid, prs_struct *data, prs_struct *rdata ) { REG_Q_OPEN_ENTRY q_u; @@ -175,6 +173,8 @@ static void api_reg_open_entry( rpcsrv_struct *p, prs_struct *data, /* construct reply. */ reg_reply_open_entry(&q_u, rdata); + + return True; } @@ -187,32 +187,19 @@ static void reg_reply_info(REG_Q_INFO *q_u, uint32 status = 0; REG_R_INFO r_u; - uint32 type = 0xcafeface; - BUFFER2 buf; - fstring name; - - ZERO_STRUCT(buf); DEBUG(5,("reg_info: %d\n", __LINE__)); - if (status == 0x0 && !get_policy_reg_name(&q_u->pol, name)) + if (status == 0 && find_lsa_policy_by_hnd(&(q_u->pol)) == -1) { status = 0xC000000 | NT_STATUS_INVALID_HANDLE; } - if (status == 0 && - strequal(name, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions")) + if (status == 0) { - char *key = "LanmanNT"; - make_buffer2(&buf, key, strlen(key)); - type = 0x1; - } - else - { - status = 0x2; /* Win32 status code. ick */ } - make_reg_r_info(&r_u, &type, &buf, status); + init_reg_r_info(&r_u, 1, "LanmanNT", 0x12, 0x12, status); /* store the response in the SMB stream */ reg_io_r_info("", &r_u, rdata, 0); @@ -223,7 +210,7 @@ static void reg_reply_info(REG_Q_INFO *q_u, /******************************************************************* api_reg_info ********************************************************************/ -static void api_reg_info( rpcsrv_struct *p, prs_struct *data, +static BOOL api_reg_info( uint16 vuid, prs_struct *data, prs_struct *rdata ) { REG_Q_INFO q_u; @@ -233,6 +220,8 @@ static void api_reg_info( rpcsrv_struct *p, prs_struct *data, /* construct reply. always indicate success */ reg_reply_info(&q_u, rdata); + + return True; } @@ -251,7 +240,7 @@ static struct api_struct api_reg_cmds[] = /******************************************************************* receives a reg pipe and responds. ********************************************************************/ -BOOL api_reg_rpc(rpcsrv_struct *p, prs_struct *data) +BOOL api_reg_rpc(pipes_struct *p, prs_struct *data) { return api_rpcTNP(p, "api_reg_rpc", api_reg_cmds, data); } diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c index 738623ec4d..169dc2169e 100644 --- a/source3/rpc_server/srv_samr.c +++ b/source3/rpc_server/srv_samr.c @@ -28,11 +28,13 @@ extern int DEBUGLEVEL; -extern fstring global_sam_name; +extern fstring global_myworkgroup; extern pstring global_myname; extern DOM_SID global_sam_sid; -extern DOM_SID global_sid_S_1_1; -extern DOM_SID global_sid_S_1_5_20; + +extern rid_name domain_group_rids[]; +extern rid_name domain_alias_rids[]; +extern rid_name builtin_alias_rids[]; /******************************************************************* This next function should be replaced with something that @@ -69,18 +71,15 @@ static BOOL get_sampwd_entries(SAM_USER_INFO_21 *pw_buf, /* skip the requested number of entries. not very efficient, but hey... */ - if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask)) - { - start_idx--; - } + start_idx--; continue; } - user_name_len = strlen(pwd->nt_name); - make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->nt_name, user_name_len); - make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len); + user_name_len = strlen(pwd->smb_name); + init_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->smb_name, user_name_len); + init_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len); pw_buf[(*num_entries)].user_rid = pwd->user_rid; - bzero( pw_buf[(*num_entries)].nt_pwd , 16); + memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16); /* Now check if the NT compatible password is available. */ if (pwd->smb_nt_passwd != NULL) @@ -91,7 +90,7 @@ static BOOL get_sampwd_entries(SAM_USER_INFO_21 *pw_buf, pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl; DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x", - (*num_entries), pwd->nt_name, + (*num_entries), pwd->smb_name, pwd->user_rid, pwd->acct_ctrl)); if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask)) @@ -121,10 +120,10 @@ static void samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u, SAMR_R_CLOSE_HND r_u; /* set up the SAMR unknown_1 response */ - bzero(r_u.pol.data, POL_HND_SIZE); + memset((char *)r_u.pol.data, '\0', POL_HND_SIZE); /* close the policy handle */ - if (close_policy_hnd(&(q_u->pol))) + if (close_lsa_policy_hnd(&(q_u->pol))) { r_u.status = 0; } @@ -145,11 +144,17 @@ static void samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u, /******************************************************************* api_samr_close_hnd ********************************************************************/ -static void api_samr_close_hnd( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_close_hnd( uint16 vuid, prs_struct *data, prs_struct *rdata) { SAMR_Q_CLOSE_HND q_u; + + /* grab the samr unknown 1 */ samr_io_q_close_hnd("", &q_u, data, 0); + + /* construct reply. always indicate success */ samr_reply_close_hnd(&q_u, rdata); + + return True; } @@ -165,19 +170,19 @@ static void samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u, r_u.status = 0x0; /* find the connection policy handle. */ - if (r_u.status == 0x0 && (find_policy_by_hnd(&(q_u->connect_pol)) == -1)) + if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1)) { r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; } /* get a (unique) handle. open a policy on it. */ - if (r_u.status == 0x0 && !(pol_open = open_policy_hnd(&(r_u.domain_pol)))) + if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.domain_pol)))) { r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; } /* associate the domain SID with the (unique) handle. */ - if (r_u.status == 0x0 && !set_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid))) + if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid))) { /* oh, whoops. don't know what error message to return, here */ r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -185,7 +190,7 @@ static void samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u, if (r_u.status != 0 && pol_open) { - close_policy_hnd(&(r_u.domain_pol)); + close_lsa_policy_hnd(&(r_u.domain_pol)); } DEBUG(5,("samr_open_domain: %d\n", __LINE__)); @@ -200,11 +205,17 @@ static void samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u, /******************************************************************* api_samr_open_domain ********************************************************************/ -static void api_samr_open_domain( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_open_domain( uint16 vuid, prs_struct *data, prs_struct *rdata) { SAMR_Q_OPEN_DOMAIN q_u; + + /* grab the samr open */ samr_io_q_open_domain("", &q_u, data, 0); + + /* construct reply. always indicate success */ samr_reply_open_domain(&q_u, rdata); + + return True; } @@ -218,18 +229,18 @@ static void samr_reply_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u, uint32 status = 0x0; /* find the policy handle. open a policy on it. */ - if (status == 0x0 && (find_policy_by_hnd(&(q_u->user_pol)) == -1)) + if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1)) { status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; } /* find the user's rid */ - if ((status == 0x0) && (get_policy_samr_rid(&(q_u->user_pol)) == 0xffffffff)) + if ((status == 0x0) && (get_lsa_policy_samr_rid(&(q_u->user_pol)) == 0xffffffff)) { - status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; + status = NT_STATUS_OBJECT_TYPE_MISMATCH; } - make_samr_r_unknown_2c(&r_u, status); + init_samr_r_unknown_2c(&r_u, status); DEBUG(5,("samr_unknown_2c: %d\n", __LINE__)); @@ -243,11 +254,17 @@ static void samr_reply_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u, /******************************************************************* api_samr_unknown_2c ********************************************************************/ -static void api_samr_unknown_2c( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_unknown_2c( uint16 vuid, prs_struct *data, prs_struct *rdata) { SAMR_Q_UNKNOWN_2C q_u; + + /* grab the samr open */ samr_io_q_unknown_2c("", &q_u, data, 0); + + /* construct reply. always indicate success */ samr_reply_unknown_2c(&q_u, rdata); + + return True; } @@ -265,37 +282,40 @@ static void samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u, status = 0x0; /* find the policy handle. open a policy on it. */ - if (status == 0x0 && (find_policy_by_hnd(&(q_u->user_pol)) == -1)) + if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1)) { status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; } /* find the user's rid */ - if (status == 0x0 && (rid = get_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff) + if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff) { - status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; + status = NT_STATUS_OBJECT_TYPE_MISMATCH; } if (status == 0x0) { - DOM_SID usr_sid; + DOM_SID user_sid; + DOM_SID everyone_sid; - usr_sid = global_sam_sid; + user_sid = global_sam_sid; - SMB_ASSERT_ARRAY(usr_sid.sub_auths, usr_sid.num_auths+1); + SMB_ASSERT_ARRAY(user_sid.sub_auths, user_sid.num_auths+1); /* * Add the user RID. */ - sid_append_rid(&usr_sid, rid); + user_sid.sub_auths[user_sid.num_auths++] = rid; - /* maybe need another 1 or 2 (S-1-5-0x20-0x220 and S-1-5-20-0x224) */ - /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */ - make_dom_sid3(&(sid[0]), 0x035b, 0x0002, &global_sid_S_1_1); - make_dom_sid3(&(sid[1]), 0x0044, 0x0002, &usr_sid); + string_to_sid(&everyone_sid, "S-1-1"); + + /* maybe need another 1 or 2 (S-1-5-0x20-0x220 and S-1-5-20-0x224) */ + /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */ + init_dom_sid3(&(sid[0]), 0x035b, 0x0002, &everyone_sid); + init_dom_sid3(&(sid[1]), 0x0044, 0x0002, &user_sid); } - make_samr_r_unknown_3(&r_u, + init_samr_r_unknown_3(&r_u, 0x0001, 0x8004, 0x00000014, 0x0002, 0x0070, 2, sid, status); @@ -312,11 +332,17 @@ static void samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u, /******************************************************************* api_samr_unknown_3 ********************************************************************/ -static void api_samr_unknown_3( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_unknown_3( uint16 vuid, prs_struct *data, prs_struct *rdata) { SAMR_Q_UNKNOWN_3 q_u; + + /* grab the samr open */ samr_io_q_unknown_3("", &q_u, data, 0); + + /* construct reply. always indicate success */ samr_reply_unknown_3(&q_u, rdata); + + return True; } @@ -332,9 +358,10 @@ static void samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u, int total_entries; r_e.status = 0x0; + r_e.total_num_entries = 0; /* find the policy handle. open a policy on it. */ - if (r_e.status == 0x0 && (find_policy_by_hnd(&(q_u->pol)) == -1)) + if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1)) { r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; } @@ -342,27 +369,16 @@ static void samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u, DEBUG(5,("samr_reply_enum_dom_users: %d\n", __LINE__)); become_root(True); - get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, - MAX_SAM_ENTRIES, q_u->acb_mask); + get_sampwd_entries(pass, 0, &total_entries, &num_entries, MAX_SAM_ENTRIES, q_u->acb_mask); unbecome_root(True); - make_samr_r_enum_dom_users(&r_e, - q_u->start_idx + num_entries, num_entries, + init_samr_r_enum_dom_users(&r_e, total_entries, + q_u->unknown_0, num_entries, pass, r_e.status); /* store the response in the SMB stream */ samr_io_r_enum_dom_users("", &r_e, rdata, 0); - if (r_e.sam != NULL) - { - free(r_e.sam); - } - - if (r_e.uni_acct_name != NULL) - { - free(r_e.uni_acct_name); - } - DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__)); } @@ -370,2278 +386,984 @@ static void samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u, /******************************************************************* api_samr_enum_dom_users ********************************************************************/ -static void api_samr_enum_dom_users( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_enum_dom_users( uint16 vuid, prs_struct *data, prs_struct *rdata) { SAMR_Q_ENUM_DOM_USERS q_e; + + /* grab the samr open */ samr_io_q_enum_dom_users("", &q_e, data, 0); + + /* construct reply. */ samr_reply_enum_dom_users(&q_e, rdata); + + return True; } /******************************************************************* - samr_reply_add_groupmem + samr_reply_enum_dom_groups ********************************************************************/ -static void samr_reply_add_groupmem(SAMR_Q_ADD_GROUPMEM *q_u, +static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u, prs_struct *rdata) { - SAMR_R_ADD_GROUPMEM r_e; - DOM_SID group_sid; - uint32 group_rid; - fstring group_sid_str; + SAMR_R_ENUM_DOM_GROUPS r_e; + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]; + int num_entries; + BOOL got_grps; + char *dummy_group = "Domain Admins"; r_e.status = 0x0; + r_e.num_entries = 0; /* find the policy handle. open a policy on it. */ - if (r_e.status == 0x0 && !get_policy_samr_sid(&q_u->pol, &group_sid)) + if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1)) { r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; } - else - { - sid_to_string(group_sid_str, &group_sid); - sid_split_rid(&group_sid, &group_rid); - } - if (r_e.status == 0x0) - { - DEBUG(10,("sid is %s\n", group_sid_str)); + DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__)); - if (sid_equal(&group_sid, &global_sam_sid)) - { - DEBUG(10,("lookup on Domain SID\n")); + got_grps = True; + num_entries = 1; + init_unistr2(&(pass[0].uni_user_name), dummy_group, strlen(dummy_group)); + pass[0].user_rid = DOMAIN_GROUP_RID_ADMINS; - become_root(True); - r_e.status = add_group_member(group_rid, q_u->rid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); - unbecome_root(True); - } - else - { - r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_GROUP; - } + if (r_e.status == 0 && got_grps) + { + init_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, pass, r_e.status); } /* store the response in the SMB stream */ - samr_io_r_add_groupmem("", &r_e, rdata, 0); + samr_io_r_enum_dom_groups("", &r_e, rdata, 0); + + DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__)); - DEBUG(5,("samr_add_groupmem: %d\n", __LINE__)); } /******************************************************************* - api_samr_add_groupmem + api_samr_enum_dom_groups ********************************************************************/ -static void api_samr_add_groupmem( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_enum_dom_groups( uint16 vuid, prs_struct *data, prs_struct *rdata) { - SAMR_Q_ADD_GROUPMEM q_e; - samr_io_q_add_groupmem("", &q_e, data, 0); - samr_reply_add_groupmem(&q_e, rdata); + SAMR_Q_ENUM_DOM_GROUPS q_e; + + /* grab the samr open */ + samr_io_q_enum_dom_groups("", &q_e, data, 0); + + /* construct reply. */ + samr_reply_enum_dom_groups(&q_e, rdata); + + return True; } + /******************************************************************* - samr_reply_del_groupmem + samr_reply_enum_dom_aliases ********************************************************************/ -static void samr_reply_del_groupmem(SAMR_Q_DEL_GROUPMEM *q_u, +static void samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u, prs_struct *rdata) { - SAMR_R_DEL_GROUPMEM r_e; - DOM_SID group_sid; - uint32 group_rid; - fstring group_sid_str; + SAMR_R_ENUM_DOM_ALIASES r_e; + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]; + int num_entries = 0; + DOM_SID sid; + fstring sid_str; + fstring sam_sid_str; r_e.status = 0x0; + r_e.num_entries = 0; /* find the policy handle. open a policy on it. */ - if (r_e.status == 0x0 && !get_policy_samr_sid(&q_u->pol, &group_sid)) + if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid)) { r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; } - else - { - sid_to_string(group_sid_str, &group_sid); - sid_split_rid(&group_sid, &group_rid); - } - if (r_e.status == 0x0) - { - DEBUG(10,("sid is %s\n", group_sid_str)); + sid_to_string(sid_str, &sid); + sid_to_string(sam_sid_str, &global_sam_sid); - if (sid_equal(&group_sid, &global_sam_sid)) - { - DEBUG(10,("lookup on Domain SID\n")); + DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str)); - become_root(True); - r_e.status = del_group_member(group_rid, q_u->rid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); - unbecome_root(True); - } - else + /* well-known aliases */ + if (strequal(sid_str, "S-1-5-32")) + { + char *name; + while (num_entries < MAX_SAM_ENTRIES && ((name = builtin_alias_rids[num_entries].name) != NULL)) { - r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_GROUP; + init_unistr2(&(pass[num_entries].uni_user_name), name, strlen(name)); + pass[num_entries].user_rid = builtin_alias_rids[num_entries].rid; + num_entries++; } } + else if (strequal(sid_str, sam_sid_str)) + { + /* local aliases */ + /* oops! there's no code to deal with this */ + DEBUG(3,("samr_reply_enum_dom_aliases: enum of aliases in our domain not supported yet\n")); + num_entries = 0; + } + + init_samr_r_enum_dom_aliases(&r_e, num_entries, pass, r_e.status); /* store the response in the SMB stream */ - samr_io_r_del_groupmem("", &r_e, rdata, 0); + samr_io_r_enum_dom_aliases("", &r_e, rdata, 0); + + DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__)); - DEBUG(5,("samr_del_groupmem: %d\n", __LINE__)); } /******************************************************************* - api_samr_del_groupmem + api_samr_enum_dom_aliases ********************************************************************/ -static void api_samr_del_groupmem( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_enum_dom_aliases( uint16 vuid, prs_struct *data, prs_struct *rdata) { - SAMR_Q_DEL_GROUPMEM q_e; - samr_io_q_del_groupmem("", &q_e, data, 0); - samr_reply_del_groupmem(&q_e, rdata); + SAMR_Q_ENUM_DOM_ALIASES q_e; + + /* grab the samr open */ + samr_io_q_enum_dom_aliases("", &q_e, data, 0); + + /* construct reply. */ + samr_reply_enum_dom_aliases(&q_e, rdata); + + return True; } + /******************************************************************* - samr_reply_add_aliasmem + samr_reply_query_dispinfo ********************************************************************/ -static void samr_reply_add_aliasmem(SAMR_Q_ADD_ALIASMEM *q_u, +static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u, prs_struct *rdata) { - SAMR_R_ADD_ALIASMEM r_e; - DOM_SID alias_sid; - uint32 alias_rid; - fstring alias_sid_str; + SAMR_R_QUERY_DISPINFO r_e; + SAM_INFO_CTR ctr; + SAM_INFO_1 info1; + SAM_INFO_2 info2; + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]; + int num_entries = 0; + int total_entries = 0; + BOOL got_pwds; + uint16 switch_level = 0x0; + + ZERO_STRUCT(r_e); r_e.status = 0x0; + DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__)); + /* find the policy handle. open a policy on it. */ - if (r_e.status == 0x0 && !get_policy_samr_sid(&q_u->alias_pol, &alias_sid)) + if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1)) { r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - else - { - sid_to_string(alias_sid_str, &alias_sid); - sid_split_rid(&alias_sid, &alias_rid); + DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n")); } if (r_e.status == 0x0) { - DEBUG(10,("sid is %s\n", alias_sid_str)); + become_root(True); + got_pwds = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0); + unbecome_root(True); - if (sid_equal(&alias_sid, &global_sam_sid)) + switch (q_u->switch_level) { - DEBUG(10,("add member on Domain SID\n")); + case 0x1: + { + + /* query disp info is for users */ + switch_level = 0x1; + init_sam_info_1(&info1, ACB_NORMAL, + q_u->start_idx, num_entries, pass); - become_root(True); - r_e.status = add_alias_member(alias_rid, &q_u->sid.sid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); - unbecome_root(True); - } - else if (sid_equal(&alias_sid, &global_sid_S_1_5_20)) - { - DEBUG(10,("add member on BUILTIN SID\n")); + ctr.sam.info1 = &info1; - become_root(True); - r_e.status = add_builtin_member(alias_rid, &q_u->sid.sid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); - unbecome_root(True); - } - else - { - r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS; + break; + } + case 0x2: + { + /* query disp info is for servers */ + switch_level = 0x2; + init_sam_info_2(&info2, ACB_WSTRUST, + q_u->start_idx, num_entries, pass); + + ctr.sam.info2 = &info2; + + break; + } } } + if (r_e.status == 0 && got_pwds) + { + init_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status); + } + /* store the response in the SMB stream */ - samr_io_r_add_aliasmem("", &r_e, rdata, 0); + samr_io_r_query_dispinfo("", &r_e, rdata, 0); + + DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__)); - DEBUG(5,("samr_add_aliasmem: %d\n", __LINE__)); } /******************************************************************* - api_samr_add_aliasmem + api_samr_query_dispinfo ********************************************************************/ -static void api_samr_add_aliasmem( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_query_dispinfo( uint16 vuid, prs_struct *data, prs_struct *rdata) { - SAMR_Q_ADD_ALIASMEM q_e; - samr_io_q_add_aliasmem("", &q_e, data, 0); - samr_reply_add_aliasmem(&q_e, rdata); + SAMR_Q_QUERY_DISPINFO q_e; + + /* grab the samr open */ + samr_io_q_query_dispinfo("", &q_e, data, 0); + + /* construct reply. */ + samr_reply_query_dispinfo(&q_e, rdata); + + return True; } + /******************************************************************* - samr_reply_del_aliasmem + samr_reply_query_aliasinfo ********************************************************************/ -static void samr_reply_del_aliasmem(SAMR_Q_DEL_ALIASMEM *q_u, +static void samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u, prs_struct *rdata) { - SAMR_R_DEL_ALIASMEM r_e; - DOM_SID alias_sid; - uint32 alias_rid; - fstring alias_sid_str; + SAMR_R_QUERY_ALIASINFO r_e; r_e.status = 0x0; + r_e.ptr = 0; /* find the policy handle. open a policy on it. */ - if (r_e.status == 0x0 && !get_policy_samr_sid(&q_u->alias_pol, &alias_sid)) + if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1)) { r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; } - else - { - sid_to_string(alias_sid_str, &alias_sid); - sid_split_rid(&alias_sid, &alias_rid); - } + + DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__)); if (r_e.status == 0x0) { - DEBUG(10,("sid is %s\n", alias_sid_str)); - - if (sid_equal(&alias_sid, &global_sam_sid)) + if (q_u->switch_level != 3) { - DEBUG(10,("del member on Domain SID\n")); - - become_root(True); - r_e.status = del_alias_member(alias_rid, &q_u->sid.sid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); - unbecome_root(True); - } - else if (sid_equal(&alias_sid, &global_sid_S_1_5_20)) - { - DEBUG(10,("del member on BUILTIN SID\n")); - - become_root(True); - r_e.status = del_builtin_member(alias_rid, &q_u->sid.sid) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); - unbecome_root(True); - } - else - { - r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS; + r_e.status = NT_STATUS_INVALID_INFO_CLASS; } } + init_samr_r_query_aliasinfo(&r_e, q_u->switch_level, + "", + r_e.status); + /* store the response in the SMB stream */ - samr_io_r_del_aliasmem("", &r_e, rdata, 0); + samr_io_r_query_aliasinfo("", &r_e, rdata, 0); + + DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__)); - DEBUG(5,("samr_del_aliasmem: %d\n", __LINE__)); } /******************************************************************* - api_samr_del_aliasmem + api_samr_query_aliasinfo ********************************************************************/ -static void api_samr_del_aliasmem( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_query_aliasinfo( uint16 vuid, prs_struct *data, prs_struct *rdata) { - SAMR_Q_DEL_ALIASMEM q_e; - samr_io_q_del_aliasmem("", &q_e, data, 0); - samr_reply_del_aliasmem(&q_e, rdata); + SAMR_Q_QUERY_ALIASINFO q_e; + + /* grab the samr open */ + samr_io_q_query_aliasinfo("", &q_e, data, 0); + + /* construct reply. */ + samr_reply_query_aliasinfo(&q_e, rdata); + + return True; } + /******************************************************************* - samr_reply_enum_domains + samr_reply_lookup_ids ********************************************************************/ -static void samr_reply_enum_domains(SAMR_Q_ENUM_DOMAINS *q_u, +static void samr_reply_lookup_ids(SAMR_Q_LOOKUP_IDS *q_u, prs_struct *rdata) { - SAMR_R_ENUM_DOMAINS r_e; - char **doms = NULL; - uint32 num_entries = 0; - - r_e.status = 0x0; - r_e.num_entries2 = 0; + uint32 rid[MAX_SAM_ENTRIES]; + uint32 status = 0; + int num_rids = q_u->num_sids1; - ZERO_STRUCT(r_e); + SAMR_R_LOOKUP_IDS r_u; - r_e.status = 0x0; + DEBUG(5,("samr_lookup_ids: %d\n", __LINE__)); - /* find the connection policy handle. */ - if (r_e.status == 0x0 && (find_policy_by_hnd(&(q_u->pol)) == -1)) + if (num_rids > MAX_SAM_ENTRIES) { - r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + num_rids = MAX_SAM_ENTRIES; + DEBUG(5,("samr_lookup_ids: truncating entries to %d\n", num_rids)); } - DEBUG(5,("samr_reply_enum_domains:\n")); +#if 0 + int i; + SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids); - if (!enumdomains(&doms, &num_entries)) + for (i = 0; i < num_rids && status == 0; i++) { - r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY; - } + struct sam_passwd *sam_pass; + fstring user_name; - if (r_e.status == 0x0) - { - make_samr_r_enum_domains(&r_e, - q_u->start_idx + num_entries, - num_entries, doms, r_e.status); - } - /* store the response in the SMB stream */ - samr_io_r_enum_domains("", &r_e, rdata, 0); + fstrcpy(user_name, unistrn2(q_u->uni_user_name[i].buffer, + q_u->uni_user_name[i].uni_str_len)); - free_char_array(num_entries, doms); + /* find the user account */ + become_root(True); + sam_pass = get_smb21pwd_entry(user_name, 0); + unbecome_root(True); - if (r_e.sam != NULL) - { - free(r_e.sam); + if (sam_pass == NULL) + { + status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; + rid[i] = 0; + } + else + { + rid[i] = sam_pass->user_rid; + } } +#endif - if (r_e.uni_dom_name != NULL) - { - free(r_e.uni_dom_name); - } + num_rids = 1; + rid[0] = BUILTIN_ALIAS_RID_USERS; + + init_samr_r_lookup_ids(&r_u, num_rids, rid, status); + + /* store the response in the SMB stream */ + samr_io_r_lookup_ids("", &r_u, rdata, 0); + + DEBUG(5,("samr_lookup_ids: %d\n", __LINE__)); - DEBUG(5,("samr_enum_domains: %d\n", __LINE__)); } /******************************************************************* - api_samr_enum_domains + api_samr_lookup_ids ********************************************************************/ -static void api_samr_enum_domains( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_lookup_ids( uint16 vuid, prs_struct *data, prs_struct *rdata) { - SAMR_Q_ENUM_DOMAINS q_e; + SAMR_Q_LOOKUP_IDS q_u; - /* grab the samr open */ - samr_io_q_enum_domains("", &q_e, data, 0); + /* grab the samr 0x10 */ + samr_io_q_lookup_ids("", &q_u, data, 0); - /* construct reply. */ - samr_reply_enum_domains(&q_e, rdata); + /* construct reply. always indicate success */ + samr_reply_lookup_ids(&q_u, rdata); + + return True; } /******************************************************************* - samr_reply_enum_dom_groups + samr_reply_lookup_names ********************************************************************/ -static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u, + +static BOOL samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u, prs_struct *rdata) { - SAMR_R_ENUM_DOM_GROUPS r_e; - DOMAIN_GRP *grps = NULL; - int num_entries = 0; - DOM_SID sid; - fstring sid_str; - - r_e.status = 0x0; - r_e.num_entries2 = 0; - - /* find the policy handle. open a policy on it. */ - if (r_e.status == 0x0 && !get_policy_samr_sid(&q_u->pol, &sid)) - { - r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } + uint32 rid[MAX_SAM_ENTRIES]; + uint8 type[MAX_SAM_ENTRIES]; + uint32 status = 0; + int i; + int num_rids = q_u->num_names1; + DOM_SID pol_sid; - sid_to_string(sid_str, &sid); + SAMR_R_LOOKUP_NAMES r_u; - DEBUG(5,("samr_reply_enum_dom_groups: sid %s\n", sid_str)); + DEBUG(5,("samr_lookup_names: %d\n", __LINE__)); - if (sid_equal(&sid, &global_sam_sid)) - { - BOOL ret; + ZERO_ARRAY(rid); + ZERO_ARRAY(type); - become_root(True); - ret = enumdomgroups(&grps, &num_entries); - unbecome_root(True); - if (!ret) - { - r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY; + if (!get_lsa_policy_samr_sid(&q_u->pol, &pol_sid)) { + status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; + init_samr_r_lookup_names(&r_u, 0, rid, type, status); + if(!samr_io_r_lookup_names("", &r_u, rdata, 0)) { + DEBUG(0,("samr_reply_lookup_names: failed to marshall SAMR_R_LOOKUP_NAMES.\n")); + return False; } - } + return True; + } - if (r_e.status == 0x0) - { - make_samr_r_enum_dom_groups(&r_e, - q_u->start_idx + num_entries, - num_entries, grps, r_e.status); + if (num_rids > MAX_SAM_ENTRIES) { + num_rids = MAX_SAM_ENTRIES; + DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids)); } - /* store the response in the SMB stream */ - samr_io_r_enum_dom_groups("", &r_e, rdata, 0); + SMB_ASSERT_ARRAY(q_u->uni_name, num_rids); - if (grps != NULL) - { - free(grps); - } - - if (r_e.sam != NULL) - { - free(r_e.sam); - } - - if (r_e.uni_grp_name != NULL) - { - free(r_e.uni_grp_name); - } - - DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__)); -} - -/******************************************************************* - api_samr_enum_dom_groups - ********************************************************************/ -static void api_samr_enum_dom_groups( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_ENUM_DOM_GROUPS q_e; - - /* grab the samr open */ - samr_io_q_enum_dom_groups("", &q_e, data, 0); - - /* construct reply. */ - samr_reply_enum_dom_groups(&q_e, rdata); -} - - -/******************************************************************* - samr_reply_enum_dom_aliases - ********************************************************************/ -static void samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u, - prs_struct *rdata) -{ - SAMR_R_ENUM_DOM_ALIASES r_e; - LOCAL_GRP *alss = NULL; - int num_entries = 0; - DOM_SID sid; - fstring sid_str; - - r_e.status = 0x0; - r_e.num_entries2 = 0; - - /* find the policy handle. open a policy on it. */ - if (r_e.status == 0x0 && !get_policy_samr_sid(&q_u->pol, &sid)) - { - r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - - sid_to_string(sid_str, &sid); - - DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str)); - - /* well-known aliases */ - if (sid_equal(&sid, &global_sid_S_1_5_20)) - { - BOOL ret; - /* builtin aliases */ - - become_root(True); - ret = enumdombuiltins(&alss, &num_entries); - unbecome_root(True); - if (!ret) - { - r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY; - } - } - else if (sid_equal(&sid, &global_sam_sid)) - { - BOOL ret; - /* local aliases */ - - become_root(True); - ret = enumdomaliases(&alss, &num_entries); - unbecome_root(True); - if (!ret) - { - r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY; - } - } - - if (r_e.status == 0x0) - { - make_samr_r_enum_dom_aliases(&r_e, - q_u->start_idx + num_entries, - num_entries, alss, r_e.status); - } - - /* store the response in the SMB stream */ - samr_io_r_enum_dom_aliases("", &r_e, rdata, 0); - - if (alss != NULL) - { - free(alss); - } - - if (r_e.sam != NULL) - { - free(r_e.sam); - } - - if (r_e.uni_grp_name != NULL) - { - free(r_e.uni_grp_name); - } - - DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__)); - -} - -/******************************************************************* - api_samr_enum_dom_aliases - ********************************************************************/ -static void api_samr_enum_dom_aliases( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_ENUM_DOM_ALIASES q_e; - - /* grab the samr open */ - samr_io_q_enum_dom_aliases("", &q_e, data, 0); - - /* construct reply. */ - samr_reply_enum_dom_aliases(&q_e, rdata); -} - - -/******************************************************************* - samr_reply_query_dispinfo - ********************************************************************/ -static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u, - prs_struct *rdata) -{ - SAMR_R_QUERY_DISPINFO r_e; - SAM_DISPINFO_CTR ctr; - SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]; - DOMAIN_GRP *grps = NULL; - DOMAIN_GRP *sam_grps = NULL; - uint32 data_size = 0; - uint32 status = 0x0; - uint16 acb_mask = ACB_NORMAL; - int num_sam_entries = 0; - int num_entries = 0; - int total_entries; - - DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__)); - - /* find the policy handle. open a policy on it. */ - if (find_policy_by_hnd(&(q_u->domain_pol)) == -1) - { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n")); - } - - if (status == 0x0) - { - become_root(True); - - /* Get what we need from the password database */ - switch (q_u->switch_level) - { - case 0x2: - { - acb_mask = ACB_WSTRUST; - /* Fall through */ - } - case 0x1: - case 0x4: - { - get_sampwd_entries(pass, q_u->start_idx, - &total_entries, &num_sam_entries, - MAX_SAM_ENTRIES, acb_mask); - break; - } - case 0x3: - case 0x5: - { - enumdomgroups(&sam_grps, &num_sam_entries); - - if (q_u->start_idx < num_sam_entries) { - grps = sam_grps + q_u->start_idx; - num_sam_entries -= q_u->start_idx; - } else { - num_sam_entries = 0; - } - break; - } - } - - unbecome_root(True); - - num_entries = num_sam_entries; - - if (num_entries > q_u->max_entries) - { - num_entries = q_u->max_entries; - } - - if (num_entries > MAX_SAM_ENTRIES) - { - num_entries = MAX_SAM_ENTRIES; - DEBUG(5,("limiting number of entries to %d\n", - num_entries)); - } - - data_size = q_u->max_size; - - /* Now create reply structure */ - switch (q_u->switch_level) - { - case 0x1: - { - ctr.sam.info1 = malloc(sizeof(SAM_DISPINFO_1)); - make_sam_dispinfo_1(ctr.sam.info1, - &num_entries, &data_size, - q_u->start_idx, pass); - break; - } - case 0x2: - { - ctr.sam.info2 = malloc(sizeof(SAM_DISPINFO_2)); - make_sam_dispinfo_2(ctr.sam.info2, - &num_entries, &data_size, - q_u->start_idx, pass); - break; - } - case 0x3: - { - ctr.sam.info3 = malloc(sizeof(SAM_DISPINFO_3)); - make_sam_dispinfo_3(ctr.sam.info3, - &num_entries, &data_size, - q_u->start_idx, grps); - break; - } - case 0x4: - { - ctr.sam.info4 = malloc(sizeof(SAM_DISPINFO_4)); - make_sam_dispinfo_4(ctr.sam.info4, - &num_entries, &data_size, - q_u->start_idx, pass); - break; - } - case 0x5: - { - ctr.sam.info5 = malloc(sizeof(SAM_DISPINFO_5)); - make_sam_dispinfo_5(ctr.sam.info5, - &num_entries, &data_size, - q_u->start_idx, grps); - break; - } - default: - { - ctr.sam.info = NULL; - status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; - break; - } - } - } - - if ((status == 0) && (num_entries < num_sam_entries)) - { - status = STATUS_MORE_ENTRIES; - } - - make_samr_r_query_dispinfo(&r_e, num_entries, data_size, - q_u->switch_level, &ctr, status); - - /* store the response in the SMB stream */ - samr_io_r_query_dispinfo("", &r_e, rdata, 0); - - /* free malloc'd areas */ - if (sam_grps != NULL) - { - free(sam_grps); - } - - if (ctr.sam.info != NULL) - { - free(ctr.sam.info); - } - - DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__)); -} - -/******************************************************************* - api_samr_query_dispinfo - ********************************************************************/ -static void api_samr_query_dispinfo( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_QUERY_DISPINFO q_e; - - samr_io_q_query_dispinfo("", &q_e, data, 0); - samr_reply_query_dispinfo(&q_e, rdata); -} - -/******************************************************************* - samr_reply_delete_dom_group - ********************************************************************/ -static void samr_reply_delete_dom_group(SAMR_Q_DELETE_DOM_GROUP *q_u, - prs_struct *rdata) -{ - uint32 status = 0; - - DOM_SID group_sid; - uint32 group_rid; - fstring group_sid_str; - - SAMR_R_DELETE_DOM_GROUP r_u; - - DEBUG(5,("samr_delete_dom_group: %d\n", __LINE__)); - - /* find the policy handle. open a policy on it. */ - if (status == 0x0 && !get_policy_samr_sid(&q_u->group_pol, &group_sid)) - { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - else - { - sid_to_string(group_sid_str, &group_sid ); - sid_split_rid(&group_sid, &group_rid); - } - - if (status == 0x0) - { - DEBUG(10,("sid is %s\n", group_sid_str)); - - if (sid_equal(&group_sid, &global_sam_sid)) - { - DEBUG(10,("lookup on Domain SID\n")); - - become_root(True); - status = del_group_entry(group_rid) ? 0x0 : (0xC0000000 | NT_STATUS_NO_SUCH_GROUP); - unbecome_root(True); - } - else - { - status = 0xC0000000 | NT_STATUS_NO_SUCH_GROUP; - } - } - - make_samr_r_delete_dom_group(&r_u, status); - - /* store the response in the SMB stream */ - samr_io_r_delete_dom_group("", &r_u, rdata, 0); -} - -/******************************************************************* - api_samr_delete_dom_group - ********************************************************************/ -static void api_samr_delete_dom_group( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_DELETE_DOM_GROUP q_u; - samr_io_q_delete_dom_group("", &q_u, data, 0); - samr_reply_delete_dom_group(&q_u, rdata); -} - - -/******************************************************************* - samr_reply_query_groupmem - ********************************************************************/ -static void samr_reply_query_groupmem(SAMR_Q_QUERY_GROUPMEM *q_u, - prs_struct *rdata) -{ - uint32 status = 0; - - DOMAIN_GRP_MEMBER *mem_grp = NULL; - uint32 *rid = NULL; - uint32 *attr = NULL; - int num_rids = 0; - DOM_SID group_sid; - uint32 group_rid; - fstring group_sid_str; - - SAMR_R_QUERY_GROUPMEM r_u; - - DEBUG(5,("samr_query_groupmem: %d\n", __LINE__)); - - /* find the policy handle. open a policy on it. */ - if (status == 0x0 && !get_policy_samr_sid(&q_u->group_pol, &group_sid)) - { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - else - { - sid_to_string(group_sid_str, &group_sid ); - sid_split_rid(&group_sid, &group_rid); - } - - if (status == 0x0) - { - DEBUG(10,("sid is %s\n", group_sid_str)); - - if (sid_equal(&group_sid, &global_sam_sid)) - { - DEBUG(10,("lookup on Domain SID\n")); - - become_root(True); - status = getgrouprid(group_rid, &mem_grp, &num_rids) != NULL ? 0x0 : (0xC0000000 | NT_STATUS_NO_SUCH_GROUP); - unbecome_root(True); - } - else - { - status = 0xC0000000 | NT_STATUS_NO_SUCH_GROUP; - } - } - - if (status == 0x0 && num_rids > 0) - { - rid = malloc(num_rids * sizeof(uint32)); - attr = malloc(num_rids * sizeof(uint32)); - if (mem_grp != NULL && rid != NULL && attr != NULL) - { - int i; - for (i = 0; i < num_rids; i++) - { - rid [i] = mem_grp[i].rid; - attr[i] = mem_grp[i].attr; - } - free(mem_grp); - } - } - - make_samr_r_query_groupmem(&r_u, num_rids, rid, attr, status); - - /* store the response in the SMB stream */ - samr_io_r_query_groupmem("", &r_u, rdata, 0); - - if (rid != NULL) - { - free(rid); - } - - if (attr != NULL) - { - free(attr); - } - - DEBUG(5,("samr_query_groupmem: %d\n", __LINE__)); - -} - -/******************************************************************* - api_samr_query_groupmem - ********************************************************************/ -static void api_samr_query_groupmem( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_QUERY_GROUPMEM q_u; - samr_io_q_query_groupmem("", &q_u, data, 0); - samr_reply_query_groupmem(&q_u, rdata); -} - - -/******************************************************************* - samr_reply_query_groupinfo - ********************************************************************/ -static void samr_reply_query_groupinfo(SAMR_Q_QUERY_GROUPINFO *q_u, - prs_struct *rdata) -{ - SAMR_R_QUERY_GROUPINFO r_e; - GROUP_INFO_CTR ctr; - uint32 status = 0x0; - - r_e.ptr = 0; - - /* find the policy handle. open a policy on it. */ - if (r_e.status == 0x0 && (find_policy_by_hnd(&(q_u->pol)) == -1)) - { - r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - - DEBUG(5,("samr_reply_query_groupinfo: %d\n", __LINE__)); - - if (status == 0x0) - { - if (q_u->switch_level == 1) - { - r_e.ptr = 1; - ctr.switch_value1 = 1; - make_samr_group_info1(&ctr.group.info1, - "fake account name", - "fake account description", 2); - } - else if (q_u->switch_level == 4) - { - r_e.ptr = 1; - ctr.switch_value1 = 4; - make_samr_group_info4(&ctr.group.info4, - "fake account description"); - } - else - { - status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; - } - } - - make_samr_r_query_groupinfo(&r_e, status == 0 ? &ctr : NULL, status); - - /* store the response in the SMB stream */ - samr_io_r_query_groupinfo("", &r_e, rdata, 0); - - DEBUG(5,("samr_query_groupinfo: %d\n", __LINE__)); - -} - -/******************************************************************* - api_samr_query_groupinfo - ********************************************************************/ -static void api_samr_query_groupinfo( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_QUERY_GROUPINFO q_e; - samr_io_q_query_groupinfo("", &q_e, data, 0); - samr_reply_query_groupinfo(&q_e, rdata); -} - - -/******************************************************************* - samr_reply_query_aliasinfo - ********************************************************************/ -static void samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u, - prs_struct *rdata) -{ - SAMR_R_QUERY_ALIASINFO r_e; - ALIAS_INFO_CTR ctr; - uint32 status = 0x0; - - r_e.ptr = 0; - - /* find the policy handle. open a policy on it. */ - if (r_e.status == 0x0 && (find_policy_by_hnd(&(q_u->pol)) == -1)) - { - r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - - DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__)); - - if (status == 0x0) - { - if (q_u->switch_level == 3) - { - r_e.ptr = 1; - ctr.switch_value1 = 3; - make_samr_alias_info3(&ctr.alias.info3, ""); - } - else - { - status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; - } - } - - make_samr_r_query_aliasinfo(&r_e, status == 0 ? &ctr : NULL, status); - - /* store the response in the SMB stream */ - samr_io_r_query_aliasinfo("", &r_e, rdata, 0); - - DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__)); - -} - -/******************************************************************* - api_samr_query_aliasinfo - ********************************************************************/ -static void api_samr_query_aliasinfo( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_QUERY_ALIASINFO q_e; - samr_io_q_query_aliasinfo("", &q_e, data, 0); - samr_reply_query_aliasinfo(&q_e, rdata); -} - - -/******************************************************************* - samr_reply_query_useraliases - ********************************************************************/ -static void samr_reply_query_useraliases(SAMR_Q_QUERY_USERALIASES *q_u, - prs_struct *rdata) -{ - uint32 status = 0; - - LOCAL_GRP *mem_grp = NULL; - uint32 *rid = NULL; - int num_rids = 0; - struct sam_passwd *sam_pass; - DOM_SID usr_sid; - DOM_SID dom_sid; - uint32 user_rid; - fstring sam_sid_str; - fstring dom_sid_str; - fstring usr_sid_str; - - SAMR_R_QUERY_USERALIASES r_u; - ZERO_STRUCT(r_u); - - DEBUG(5,("samr_query_useraliases: %d\n", __LINE__)); - - /* find the policy handle. open a policy on it. */ - if (status == 0x0 && !get_policy_samr_sid(&q_u->pol, &dom_sid)) - { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - else - { - sid_to_string(dom_sid_str, &dom_sid ); - sid_to_string(sam_sid_str, &global_sam_sid); - } - - if (status == 0x0) - { - usr_sid = q_u->sid[0].sid; - sid_split_rid(&usr_sid, &user_rid); - sid_to_string(usr_sid_str, &usr_sid); - - } - - if (status == 0x0) - { - /* find the user account */ - become_root(True); - sam_pass = getsam21pwrid(user_rid); - unbecome_root(True); - - if (sam_pass == NULL) - { - status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; - num_rids = 0; - } - } - - if (status == 0x0) - { - DEBUG(10,("sid is %s\n", dom_sid_str)); - - if (sid_equal(&dom_sid, &global_sid_S_1_5_20)) - { - DEBUG(10,("lookup on S-1-5-20\n")); - - become_root(True); - getuserbuiltinntnam(sam_pass->nt_name, &mem_grp, &num_rids); - unbecome_root(True); - } - else if (sid_equal(&dom_sid, &usr_sid)) - { - DEBUG(10,("lookup on Domain SID\n")); - - become_root(True); - getuseraliasntnam(sam_pass->nt_name, &mem_grp, &num_rids); - unbecome_root(True); - } - else - { - status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; - } - } - - if (status == 0x0 && num_rids > 0) - { - rid = malloc(num_rids * sizeof(uint32)); - if (mem_grp != NULL && rid != NULL) - { - int i; - for (i = 0; i < num_rids; i++) - { - rid[i] = mem_grp[i].rid; - } - free(mem_grp); - } - } - - make_samr_r_query_useraliases(&r_u, num_rids, rid, status); - - /* store the response in the SMB stream */ - samr_io_r_query_useraliases("", &r_u, rdata, 0); - - if (rid != NULL) - { - free(rid); - } - - DEBUG(5,("samr_query_useraliases: %d\n", __LINE__)); - -} - -/******************************************************************* - api_samr_query_useraliases - ********************************************************************/ -static void api_samr_query_useraliases( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_QUERY_USERALIASES q_u; - ZERO_STRUCT(q_u); - samr_io_q_query_useraliases("", &q_u, data, 0); - samr_reply_query_useraliases(&q_u, rdata); - samr_free_q_query_useraliases(&q_u); -} - -/******************************************************************* - samr_reply_delete_dom_alias - ********************************************************************/ -static void samr_reply_delete_dom_alias(SAMR_Q_DELETE_DOM_ALIAS *q_u, - prs_struct *rdata) -{ - uint32 status = 0; - - DOM_SID alias_sid; - uint32 alias_rid; - fstring alias_sid_str; - - SAMR_R_DELETE_DOM_ALIAS r_u; - - DEBUG(5,("samr_delete_dom_alias: %d\n", __LINE__)); - - /* find the policy handle. open a policy on it. */ - if (status == 0x0 && !get_policy_samr_sid(&q_u->alias_pol, &alias_sid)) - { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - else - { - sid_to_string(alias_sid_str, &alias_sid ); - sid_split_rid(&alias_sid, &alias_rid); - } - - if (status == 0x0) - { - DEBUG(10,("sid is %s\n", alias_sid_str)); - - if (sid_equal(&alias_sid, &global_sam_sid)) - { - DEBUG(10,("lookup on Domain SID\n")); - - become_root(True); - status = del_alias_entry(alias_rid) ? 0x0 : (0xC0000000 | NT_STATUS_NO_SUCH_ALIAS); - unbecome_root(True); - } - else - { - status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS; - } - } - - make_samr_r_delete_dom_alias(&r_u, status); - - /* store the response in the SMB stream */ - samr_io_r_delete_dom_alias("", &r_u, rdata, 0); -} - -/******************************************************************* - api_samr_delete_dom_alias - ********************************************************************/ -static void api_samr_delete_dom_alias( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_DELETE_DOM_ALIAS q_u; - samr_io_q_delete_dom_alias("", &q_u, data, 0); - samr_reply_delete_dom_alias(&q_u, rdata); -} - - -/******************************************************************* - samr_reply_query_aliasmem - ********************************************************************/ -static void samr_reply_query_aliasmem(SAMR_Q_QUERY_ALIASMEM *q_u, - prs_struct *rdata) -{ - uint32 status = 0; - - LOCAL_GRP_MEMBER *mem_grp = NULL; - DOM_SID2 *sid = NULL; - int num_sids = 0; - DOM_SID alias_sid; - uint32 alias_rid; - fstring alias_sid_str; - - SAMR_R_QUERY_ALIASMEM r_u; - - DEBUG(5,("samr_query_aliasmem: %d\n", __LINE__)); - - /* find the policy handle. open a policy on it. */ - if (status == 0x0 && !get_policy_samr_sid(&q_u->alias_pol, &alias_sid)) - { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - else - { - sid_to_string(alias_sid_str, &alias_sid ); - sid_split_rid(&alias_sid, &alias_rid); - } - - if (status == 0x0) - { - DEBUG(10,("sid is %s\n", alias_sid_str)); - - if (sid_equal(&alias_sid, &global_sid_S_1_5_20)) - { - DEBUG(10,("lookup on S-1-5-20\n")); - - become_root(True); - status = getbuiltinrid(alias_rid, &mem_grp, &num_sids) != NULL ? 0x0 : 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS; - unbecome_root(True); - } - else if (sid_equal(&alias_sid, &global_sam_sid)) - { - DEBUG(10,("lookup on Domain SID\n")); - - become_root(True); - status = getaliasrid(alias_rid, &mem_grp, &num_sids) != NULL ? 0x0 : 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS; - unbecome_root(True); - } - else - { - status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS; - } - } - - if (status == 0x0 && num_sids > 0) - { - sid = malloc(num_sids * sizeof(DOM_SID)); - if (mem_grp != NULL && sid != NULL) - { - int i; - for (i = 0; i < num_sids; i++) - { - make_dom_sid2(&sid[i], &mem_grp[i].sid); - } - free(mem_grp); - } - } - - make_samr_r_query_aliasmem(&r_u, num_sids, sid, status); - - /* store the response in the SMB stream */ - samr_io_r_query_aliasmem("", &r_u, rdata, 0); - - if (sid != NULL) - { - free(sid); - } - - DEBUG(5,("samr_query_aliasmem: %d\n", __LINE__)); - -} - -/******************************************************************* - api_samr_query_aliasmem - ********************************************************************/ -static void api_samr_query_aliasmem( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_QUERY_ALIASMEM q_u; - samr_io_q_query_aliasmem("", &q_u, data, 0); - samr_reply_query_aliasmem(&q_u, rdata); -} - -/******************************************************************* - samr_reply_lookup_names - ********************************************************************/ -static void samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u, - prs_struct *rdata) -{ - uint32 rid [MAX_SAM_ENTRIES]; - uint8 type[MAX_SAM_ENTRIES]; - uint32 status = 0; - int i; - int num_rids = q_u->num_names1; - DOM_SID pol_sid; - - SAMR_R_LOOKUP_NAMES r_u; - - DEBUG(5,("samr_lookup_names: %d\n", __LINE__)); - - if (status == 0x0 && !get_policy_samr_sid(&q_u->pol, &pol_sid)) - { - status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; - } - - if (num_rids > MAX_SAM_ENTRIES) - { - num_rids = MAX_SAM_ENTRIES; - DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids)); - } - - SMB_ASSERT_ARRAY(q_u->uni_name, num_rids); - - for (i = 0; i < num_rids && status == 0; i++) - { - DOM_SID sid; - fstring name; - unistr2_to_ascii(name, &q_u->uni_name[i], sizeof(name)-1); - - status = lookup_name(name, &sid, &(type[i])); - if (status == 0x0) - { - sid_split_rid(&sid, &rid[i]); - } - else - { - type[i] = SID_NAME_UNKNOWN; - rid [i] = 0xffffffff; - } - if (!sid_equal(&pol_sid, &sid)) - { - rid [i] = 0xffffffff; - type[i] = SID_NAME_UNKNOWN; - } - } - - make_samr_r_lookup_names(&r_u, num_rids, rid, type, status); - - /* store the response in the SMB stream */ - samr_io_r_lookup_names("", &r_u, rdata, 0); - - DEBUG(5,("samr_lookup_names: %d\n", __LINE__)); - -} - -/******************************************************************* - api_samr_lookup_names - ********************************************************************/ -static void api_samr_lookup_names( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_LOOKUP_NAMES q_u; - samr_io_q_lookup_names("", &q_u, data, 0); - samr_reply_lookup_names(&q_u, rdata); -} - -/******************************************************************* - samr_reply_chgpasswd_user - ********************************************************************/ -static void samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u, - prs_struct *rdata) -{ - SAMR_R_CHGPASSWD_USER r_u; - uint32 status = 0x0; - fstring user_name; - fstring wks; - - unistr2_to_ascii(user_name, &q_u->uni_user_name, sizeof(user_name)-1); - unistr2_to_ascii(wks, &q_u->uni_dest_host, sizeof(wks)-1); - - DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks)); - - if (!pass_oem_change(user_name, - q_u->lm_newpass.pass, q_u->lm_oldhash.hash, - q_u->nt_newpass.pass, q_u->nt_oldhash.hash)) - { - status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD; - } - - make_samr_r_chgpasswd_user(&r_u, status); - - /* store the response in the SMB stream */ - samr_io_r_chgpasswd_user("", &r_u, rdata, 0); - - DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__)); -} - -/******************************************************************* - api_samr_chgpasswd_user - ********************************************************************/ -static void api_samr_chgpasswd_user( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_CHGPASSWD_USER q_u; - samr_io_q_chgpasswd_user("", &q_u, data, 0); - samr_reply_chgpasswd_user(&q_u, rdata); -} - - -/******************************************************************* - samr_reply_unknown_38 - ********************************************************************/ -static void samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u, - prs_struct *rdata) -{ - SAMR_R_UNKNOWN_38 r_u; - - DEBUG(5,("samr_unknown_38: %d\n", __LINE__)); - - make_samr_r_unknown_38(&r_u); - - /* store the response in the SMB stream */ - samr_io_r_unknown_38("", &r_u, rdata, 0); - - DEBUG(5,("samr_unknown_38: %d\n", __LINE__)); -} - -/******************************************************************* - api_samr_unknown_38 - ********************************************************************/ -static void api_samr_unknown_38( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_UNKNOWN_38 q_u; - samr_io_q_unknown_38("", &q_u, data, 0); - samr_reply_unknown_38(&q_u, rdata); -} - - -/******************************************************************* - samr_reply_lookup_rids - ********************************************************************/ -static void samr_reply_lookup_rids(SAMR_Q_LOOKUP_RIDS *q_u, - prs_struct *rdata) -{ - fstring group_names[MAX_SAM_ENTRIES]; - uint8 group_attrs[MAX_SAM_ENTRIES]; - uint32 status = 0; - int num_rids = q_u->num_rids1; - DOM_SID pol_sid; - - SAMR_R_LOOKUP_RIDS r_u; - ZERO_STRUCT(r_u); - - DEBUG(5,("samr_lookup_rids: %d\n", __LINE__)); - - /* find the policy handle. open a policy on it. */ - if (status == 0x0 && (find_policy_by_hnd(&(q_u->pol)) == -1)) - { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - - if (status == 0x0 && !get_policy_samr_sid(&q_u->pol, &pol_sid)) - { - status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; - } - - if (status == 0x0) - { - int i; - if (num_rids > MAX_SAM_ENTRIES) - { - num_rids = MAX_SAM_ENTRIES; - DEBUG(5,("samr_lookup_rids: truncating entries to %d\n", num_rids)); - } - - for (i = 0; i < num_rids && status == 0; i++) - { - DOM_SID sid; - sid_copy(&sid, &pol_sid); - sid_append_rid(&sid, q_u->rid[i]); - lookup_sid(&sid, group_names[i], &group_attrs[i]); - } - } - - make_samr_r_lookup_rids(&r_u, num_rids, group_names, group_attrs, status); - - /* store the response in the SMB stream */ - samr_io_r_lookup_rids("", &r_u, rdata, 0); - - DEBUG(5,("samr_lookup_rids: %d\n", __LINE__)); - -} - -/******************************************************************* - api_samr_lookup_rids - ********************************************************************/ -static void api_samr_lookup_rids( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_LOOKUP_RIDS q_u; - ZERO_STRUCT(q_u); - samr_io_q_lookup_rids("", &q_u, data, 0); - samr_reply_lookup_rids(&q_u, rdata); - samr_free_q_lookup_rids(&q_u); -} - - -/******************************************************************* - samr_reply_open_user - ********************************************************************/ -static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u, - prs_struct *rdata, - int status) -{ - SAMR_R_OPEN_USER r_u; - struct sam_passwd *sam_pass; - BOOL pol_open = False; - - /* set up the SAMR open_user response */ - bzero(r_u.user_pol.data, POL_HND_SIZE); - - r_u.status = 0x0; - - /* find the policy handle. open a policy on it. */ - if (r_u.status == 0x0 && (find_policy_by_hnd(&(q_u->domain_pol)) == -1)) - { - r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } + for (i = 0; i < num_rids; i++) { + fstring name; - /* get a (unique) handle. open a policy on it. */ - if (r_u.status == 0x0 && !(pol_open = open_policy_hnd(&(r_u.user_pol)))) - { - r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } + status = 0xC0000000 | NT_STATUS_NONE_MAPPED; - become_root(True); - sam_pass = getsam21pwrid(q_u->user_rid); - unbecome_root(True); + rid [i] = 0xffffffff; + type[i] = SID_NAME_UNKNOWN; - /* check that the RID exists in our domain. */ - if (r_u.status == 0x0 && sam_pass == NULL) - { - r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; - } + fstrcpy(name, dos_unistrn2(q_u->uni_name[i].buffer, + q_u->uni_name[i].uni_str_len)); - /* associate the RID with the (unique) handle. */ - if (r_u.status == 0x0 && !set_policy_samr_rid(&(r_u.user_pol), q_u->user_rid)) - { - /* oh, whoops. don't know what error message to return, here */ - r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } + if(sid_equal(&pol_sid, &global_sam_sid)) { + DOM_SID sid; - if (r_u.status != 0 && pol_open) - { - close_policy_hnd(&(r_u.user_pol)); + if(lookup_local_name(global_myname, name, &sid, &type[i])) { + sid_split_rid( &sid, &rid[i]); + status = 0; + } + } } - DEBUG(5,("samr_open_user: %d\n", __LINE__)); + init_samr_r_lookup_names(&r_u, num_rids, rid, type, status); /* store the response in the SMB stream */ - samr_io_r_open_user("", &r_u, rdata, 0); + if(!samr_io_r_lookup_names("", &r_u, rdata, 0)) { + DEBUG(0,("samr_reply_lookup_names: failed to marshall SAMR_R_LOOKUP_NAMES.\n")); + return False; + } - DEBUG(5,("samr_open_user: %d\n", __LINE__)); + DEBUG(5,("samr_lookup_names: %d\n", __LINE__)); + return True; } /******************************************************************* - api_samr_open_user + api_samr_lookup_names ********************************************************************/ -static void api_samr_open_user( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_OPEN_USER q_u; - samr_io_q_open_user("", &q_u, data, 0); - samr_reply_open_user(&q_u, rdata, 0x0); -} - -/************************************************************************* - get_user_info_10 - *************************************************************************/ -static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid) +static BOOL api_samr_lookup_names( uint16 vuid, prs_struct *data, prs_struct *rdata) { - struct sam_passwd *sam_pass; + SAMR_Q_LOOKUP_NAMES q_u; - become_root(True); - sam_pass = getsam21pwrid(user_rid); - unbecome_root(True); + memset(&q_u, '\0', sizeof(q_u)); - if (sam_pass == NULL) - { - DEBUG(4,("User 0x%x not found\n", user_rid)); + /* grab the samr lookup names */ + if(!samr_io_q_lookup_names("", &q_u, data, 0)) { + DEBUG(0,("api_samr_lookup_names: failed to unmarshall SAMR_Q_LOOKUP_NAMES.\n")); return False; } - DEBUG(3,("User:[%s]\n", sam_pass->nt_name)); - - make_sam_user_info10(id10, sam_pass->acct_ctrl); - - return True; -} - -/************************************************************************* - get_user_info_21 - *************************************************************************/ -static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid) -{ - struct sam_passwd *sam_pass; - LOGON_HRS hrs; - int i; - - become_root(True); - sam_pass = getsam21pwrid(user_rid); - unbecome_root(True); - - if (sam_pass == NULL) - { - DEBUG(4,("User 0x%x not found\n", user_rid)); + /* construct reply. always indicate success */ + if(!samr_reply_lookup_names(&q_u, rdata)) return False; - } - - DEBUG(3,("User:[%s]\n", sam_pass->nt_name)); - - /* create a LOGON_HRS structure */ - hrs.len = sam_pass->hours_len; - SMB_ASSERT_ARRAY(hrs.hours, hrs.len); - for (i = 0; i < hrs.len; i++) - { - hrs.hours[i] = sam_pass->hours[i]; - } - - make_sam_user_info21(id21, - - &sam_pass->logon_time, - &sam_pass->logoff_time, - &sam_pass->kickoff_time, - &sam_pass->pass_last_set_time, - &sam_pass->pass_can_change_time, - &sam_pass->pass_must_change_time, - - sam_pass->nt_name, /* user_name */ - sam_pass->full_name, /* full_name */ - sam_pass->home_dir, /* home_dir */ - sam_pass->dir_drive, /* dir_drive */ - sam_pass->logon_script, /* logon_script */ - sam_pass->profile_path, /* profile_path */ - sam_pass->acct_desc, /* description */ - sam_pass->workstations, /* workstations user can log in from */ - sam_pass->unknown_str, /* don't know, yet */ - sam_pass->munged_dial, /* dialin info. contains dialin path and tel no */ - - sam_pass->user_rid, /* RID user_id */ - sam_pass->group_rid, /* RID group_id */ - sam_pass->acct_ctrl, - - sam_pass->unknown_3, /* unknown_3 */ - sam_pass->logon_divs, /* divisions per week */ - &hrs, /* logon hours */ - sam_pass->unknown_5, - sam_pass->unknown_6); return True; } /******************************************************************* - samr_reply_query_userinfo + samr_reply_chgpasswd_user ********************************************************************/ -static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u, + +static BOOL samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u, prs_struct *rdata) { - SAMR_R_QUERY_USERINFO r_u; -#if 0 - SAM_USER_INFO_11 id11; -#endif - SAM_USER_INFO_10 id10; - SAM_USER_INFO_21 id21; - void *info = NULL; - + SAMR_R_CHGPASSWD_USER r_u; uint32 status = 0x0; - uint32 rid = 0x0; - - DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__)); - - /* search for the handle */ - if (status == 0x0 && (find_policy_by_hnd(&(q_u->pol)) == -1)) - { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } + fstring user_name; + fstring wks; - /* find the user's rid */ - if (status == 0x0 && (rid = get_policy_samr_rid(&(q_u->pol))) == 0xffffffff) - { - status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; - } + fstrcpy(user_name, dos_unistrn2(q_u->uni_user_name.buffer, q_u->uni_user_name.uni_str_len)); + fstrcpy(wks , dos_unistrn2(q_u->uni_dest_host.buffer, q_u->uni_dest_host.uni_str_len)); - DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid)); + DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks)); - /* ok! user info levels (there are lots: see MSDEV help), off we go... */ - if (status == 0x0) + if (!pass_oem_change(user_name, + q_u->lm_newpass.pass, q_u->lm_oldhash.hash, + q_u->nt_newpass.pass, q_u->nt_oldhash.hash)) { - switch (q_u->switch_value) - { - case 0x10: - { - info = (void*)&id10; - status = get_user_info_10(&id10, rid) ? 0 : (0xC0000000 | NT_STATUS_NO_SUCH_USER); - break; - } -#if 0 -/* whoops - got this wrong. i think. or don't understand what's happening. */ - case 0x11: - { - NTTIME expire; - info = (void*)&id11; - - expire.low = 0xffffffff; - expire.high = 0x7fffffff; - - make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080); - - break; - } -#endif - case 21: - { - info = (void*)&id21; - status = get_user_info_21(&id21, rid) ? 0 : (0xC0000000 | NT_STATUS_NO_SUCH_USER); - break; - } - - default: - { - status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; - - break; - } - } + status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD; } - make_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status); + init_samr_r_chgpasswd_user(&r_u, status); /* store the response in the SMB stream */ - samr_io_r_query_userinfo("", &r_u, rdata, 0); - - DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__)); - -} - -/******************************************************************* - set_user_info_24 - ********************************************************************/ -static BOOL set_user_info_24(SAM_USER_INFO_24 *id24, uint32 rid) -{ - struct sam_passwd *pwd = getsam21pwrid(rid); - struct sam_passwd new_pwd; - static uchar nt_hash[16]; - static uchar lm_hash[16]; - UNISTR2 new_pw; - uint32 len; - - if (pwd == NULL) - { + if(!samr_io_r_chgpasswd_user("", &r_u, rdata, 0)) { + DEBUG(0,("samr_reply_chgpasswd_user: Failed to marshall SAMR_R_CHGPASSWD_USER struct.\n" )); return False; } - pwdb_init_sam(&new_pwd); - copy_sam_passwd(&new_pwd, pwd); - - if (!decode_pw_buffer(id24->pass, (char *)new_pw.buffer, 256, &len)) - { - return False; - } - - new_pw.uni_max_len = len / 2; - new_pw.uni_str_len = len / 2; - - nt_lm_owf_genW(&new_pw, nt_hash, lm_hash); - - new_pwd.smb_passwd = lm_hash; - new_pwd.smb_nt_passwd = nt_hash; - - return mod_sam21pwd_entry(&new_pwd, True); + DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__)); + return True; } /******************************************************************* - set_user_info_23 + api_samr_chgpasswd_user ********************************************************************/ -static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid) + +static BOOL api_samr_chgpasswd_user( uint16 vuid, prs_struct *data, prs_struct *rdata) { - struct sam_passwd *pwd = getsam21pwrid(rid); - struct sam_passwd new_pwd; - static uchar nt_hash[16]; - static uchar lm_hash[16]; - UNISTR2 new_pw; - uint32 len; - - if (id23 == NULL) - { - DEBUG(5, ("set_user_info_23: NULL id23\n")); - return False; - } - if (pwd == NULL) - { + SAMR_Q_CHGPASSWD_USER q_u; + + /* unknown 38 command */ + if (!samr_io_q_chgpasswd_user("", &q_u, data, 0)) { + DEBUG(0,("api_samr_chgpasswd_user: samr_io_q_chgpasswd_user failed to parse RPC packet.\n")); return False; } - pwdb_init_sam(&new_pwd); - copy_sam_passwd(&new_pwd, pwd); - copy_id23_to_sam_passwd(&new_pwd, id23); - - if (!decode_pw_buffer(id23->pass, (char*)new_pw.buffer, 256, &len)) - { + /* construct reply. */ + if(!samr_reply_chgpasswd_user(&q_u, rdata)) { + DEBUG(0,("api_samr_chgpasswd_user: samr_reply_chgpasswd_user failed to create reply packet.\n")); return False; } - new_pw.uni_max_len = len / 2; - new_pw.uni_str_len = len / 2; - - nt_lm_owf_genW(&new_pw, nt_hash, lm_hash); - - new_pwd.smb_passwd = lm_hash; - new_pwd.smb_nt_passwd = nt_hash; - - return mod_sam21pwd_entry(&new_pwd, True); + return True; } + /******************************************************************* - set_user_info_16 + samr_reply_unknown_38 ********************************************************************/ -static BOOL set_user_info_16(SAM_USER_INFO_16 *id16, uint32 rid) +static void samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u, + prs_struct *rdata) { - struct sam_passwd *pwd = getsam21pwrid(rid); - struct sam_passwd new_pwd; + SAMR_R_UNKNOWN_38 r_u; - if (id16 == NULL) - { - DEBUG(5, ("set_user_info_16: NULL id16\n")); - return False; - } - if (pwd == NULL) - { - return False; - } + DEBUG(5,("samr_unknown_38: %d\n", __LINE__)); - copy_sam_passwd(&new_pwd, pwd); + init_samr_r_unknown_38(&r_u); - new_pwd.acct_ctrl = id16->acb_info; + /* store the response in the SMB stream */ + samr_io_r_unknown_38("", &r_u, rdata, 0); - return mod_sam21pwd_entry(&new_pwd, True); + DEBUG(5,("samr_unknown_38: %d\n", __LINE__)); } /******************************************************************* - api_samr_query_userinfo + api_samr_unknown_38 ********************************************************************/ -static void api_samr_query_userinfo( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_unknown_38( uint16 vuid, prs_struct *data, prs_struct *rdata) { - SAMR_Q_QUERY_USERINFO q_u; - samr_io_q_query_userinfo("", &q_u, data, 0); - samr_reply_query_userinfo(&q_u, rdata); + SAMR_Q_UNKNOWN_38 q_u; + + /* unknown 38 command */ + samr_io_q_unknown_38("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_unknown_38(&q_u, rdata); + + return True; } /******************************************************************* - samr_reply_set_userinfo2 + samr_reply_unknown_12 ********************************************************************/ -static void samr_reply_set_userinfo2(SAMR_Q_SET_USERINFO2 *q_u, - prs_struct *rdata, uchar user_sess_key[16]) +static void samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u, + prs_struct *rdata) { - SAMR_R_SET_USERINFO2 r_u; + fstring group_names[MAX_SAM_ENTRIES]; + uint32 group_attrs[MAX_SAM_ENTRIES]; + uint32 status = 0; + int num_gids = q_u->num_gids1; - uint32 status = 0x0; - uint32 rid = 0x0; + SAMR_R_UNKNOWN_12 r_u; - DEBUG(5,("samr_reply_set_userinfo2: %d\n", __LINE__)); + DEBUG(5,("samr_unknown_12: %d\n", __LINE__)); - /* search for the handle */ - if (status == 0x0 && (find_policy_by_hnd(&(q_u->pol)) == -1)) + /* find the policy handle. open a policy on it. */ + if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1)) { status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; } - /* find the user's rid */ - if (status == 0x0 && (rid = get_policy_samr_rid(&(q_u->pol))) == 0xffffffff) - { - status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; - } - - DEBUG(5,("samr_reply_set_userinfo2: rid:0x%x\n", rid)); - - /* ok! user info levels (there are lots: see MSDEV help), off we go... */ - if (status == 0x0 && q_u->info.id == NULL) - { - DEBUG(5,("samr_reply_set_userinfo2: NULL info level\n")); - status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; - } - if (status == 0x0) { - switch (q_u->switch_value) + int i; + if (num_gids > MAX_SAM_ENTRIES) { - case 16: - { - SAM_USER_INFO_16 *id16 = q_u->info.id16; - status = set_user_info_16(id16, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); - break; - } - default: - { - status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + num_gids = MAX_SAM_ENTRIES; + DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids)); + } - break; - } + for (i = 0; i < num_gids && status == 0; i++) + { + fstrcpy(group_names[i], "dummy group"); + group_attrs[i] = 0x2; } } - make_samr_r_set_userinfo2(&r_u, status); + init_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status); /* store the response in the SMB stream */ - samr_io_r_set_userinfo2("", &r_u, rdata, 0); + samr_io_r_unknown_12("", &r_u, rdata, 0); - DEBUG(5,("samr_reply_set_userinfo2: %d\n", __LINE__)); + DEBUG(5,("samr_unknown_12: %d\n", __LINE__)); } /******************************************************************* - api_samr_set_userinfo2 + api_samr_unknown_12 ********************************************************************/ -static void api_samr_set_userinfo2( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_unknown_12( uint16 vuid, prs_struct *data, prs_struct *rdata) { - SAMR_Q_SET_USERINFO2 q_u; - ZERO_STRUCT(q_u); + SAMR_Q_UNKNOWN_12 q_u; - samr_io_q_set_userinfo2("", &q_u, data, 0); - samr_reply_set_userinfo2(&q_u, rdata, p->user_sess_key); + /* grab the samr lookup names */ + samr_io_q_unknown_12("", &q_u, data, 0); - if (q_u.info.id != NULL) - { - free(q_u.info.id); - } + /* construct reply. always indicate success */ + samr_reply_unknown_12(&q_u, rdata); + + return True; } /******************************************************************* - samr_reply_set_userinfo + samr_reply_open_user ********************************************************************/ -static void samr_reply_set_userinfo(SAMR_Q_SET_USERINFO *q_u, - prs_struct *rdata, uchar user_sess_key[16]) +static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u, + prs_struct *rdata, + int status) { - SAMR_R_SET_USERINFO r_u; + SAMR_R_OPEN_USER r_u; + struct sam_passwd *sam_pass; + BOOL pol_open = False; - uint32 status = 0x0; - uint32 rid = 0x0; + /* set up the SAMR open_user response */ + memset((char *)r_u.user_pol.data, '\0', POL_HND_SIZE); - DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__)); + r_u.status = 0x0; - /* search for the handle */ - if (status == 0x0 && (find_policy_by_hnd(&(q_u->pol)) == -1)) + /* find the policy handle. open a policy on it. */ + if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1)) { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; } - /* find the user's rid */ - if (status == 0x0 && (rid = get_policy_samr_rid(&(q_u->pol))) == 0xffffffff) + /* get a (unique) handle. open a policy on it. */ + if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol)))) { - status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; } - DEBUG(5,("samr_reply_set_userinfo: rid:0x%x\n", rid)); + become_root(True); + sam_pass = getsam21pwrid(q_u->user_rid); + unbecome_root(True); - /* ok! user info levels (there are lots: see MSDEV help), off we go... */ - if (status == 0x0 && q_u->info.id == NULL) + /* check that the RID exists in our domain. */ + if (r_u.status == 0x0 && sam_pass == NULL) { - DEBUG(5,("samr_reply_set_userinfo: NULL info level\n")); - status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; } - if (status == 0x0) + /* associate the RID with the (unique) handle. */ + if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid)) { - switch (q_u->switch_value) - { - case 24: - { - SAM_USER_INFO_24 *id24 = q_u->info.id24; - SamOEMhash(id24->pass, user_sess_key, True); - status = set_user_info_24(id24, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); - break; - } - - case 23: - { - SAM_USER_INFO_23 *id23 = q_u->info.id23; - SamOEMhash(id23->pass, user_sess_key, 1); -#if DEBUG_PASSWORD - DEBUG(100,("pass buff:\n")); - dump_data(100, id23->pass, sizeof(id23->pass)); -#endif - dbgflush(); - - status = set_user_info_23(id23, rid) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); - break; - } - - default: - { - status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + /* oh, whoops. don't know what error message to return, here */ + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } - break; - } - } + if (r_u.status != 0 && pol_open) + { + close_lsa_policy_hnd(&(r_u.user_pol)); } - make_samr_r_set_userinfo(&r_u, status); + DEBUG(5,("samr_open_user: %d\n", __LINE__)); /* store the response in the SMB stream */ - samr_io_r_set_userinfo("", &r_u, rdata, 0); + samr_io_r_open_user("", &r_u, rdata, 0); - DEBUG(5,("samr_reply_set_userinfo: %d\n", __LINE__)); + DEBUG(5,("samr_open_user: %d\n", __LINE__)); } /******************************************************************* - api_samr_set_userinfo + api_samr_open_user ********************************************************************/ -static void api_samr_set_userinfo( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_open_user( uint16 vuid, prs_struct *data, prs_struct *rdata) { - SAMR_Q_SET_USERINFO q_u; - ZERO_STRUCT(q_u); + SAMR_Q_OPEN_USER q_u; -#ifdef DEBUG_PASSWORD - DEBUG(100,("set user info: sess_key: ")); - dump_data(100, p->user_sess_key, 16); -#endif - samr_io_q_set_userinfo("", &q_u, data, 0); - samr_reply_set_userinfo(&q_u, rdata, p->user_sess_key); + /* grab the samr unknown 22 */ + samr_io_q_open_user("", &q_u, data, 0); - if (q_u.info.id != NULL) - { - free(q_u.info.id); - } + /* construct reply. always indicate success */ + samr_reply_open_user(&q_u, rdata, 0x0); + + return True; } -/******************************************************************* - samr_reply_query_usergroups - ********************************************************************/ -static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u, - prs_struct *rdata) +/************************************************************************* + get_user_info_10 + *************************************************************************/ +static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid) { - SAMR_R_QUERY_USERGROUPS r_u; - uint32 status = 0x0; - - struct sam_passwd *sam_pass; - DOM_GID *gids = NULL; - int num_groups = 0; - uint32 rid; - - DEBUG(5,("samr_query_usergroups: %d\n", __LINE__)); + struct smb_passwd *smb_pass; - /* find the policy handle. open a policy on it. */ - if (status == 0x0 && (find_policy_by_hnd(&(q_u->pol)) == -1)) + if (!pdb_rid_is_user(user_rid)) { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + DEBUG(4,("RID 0x%x is not a user RID\n", user_rid)); + return False; } - /* find the user's rid */ - if (status == 0x0 && (rid = get_policy_samr_rid(&(q_u->pol))) == 0xffffffff) - { - status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; - } + become_root(True); + smb_pass = getsmbpwrid(user_rid); + unbecome_root(True); - if (status == 0x0) + if (smb_pass == NULL) { - become_root(True); - sam_pass = getsam21pwrid(rid); - unbecome_root(True); - - if (sam_pass == NULL) - { - status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; - } + DEBUG(4,("User 0x%x not found\n", user_rid)); + return False; } - if (status == 0x0) - { - DOMAIN_GRP *mem_grp = NULL; - - become_root(True); - getusergroupsntnam(sam_pass->nt_name, &mem_grp, &num_groups); - unbecome_root(True); - - gids = NULL; - num_groups = make_dom_gids(mem_grp, num_groups, &gids); + DEBUG(3,("User:[%s]\n", smb_pass->smb_name)); - if (mem_grp != NULL) - { - free(mem_grp); - } - } + init_sam_user_info10(id10, smb_pass->acct_ctrl); - /* construct the response. lkclXXXX: gids are not copied! */ - make_samr_r_query_usergroups(&r_u, num_groups, gids, status); + return True; +} - /* store the response in the SMB stream */ - samr_io_r_query_usergroups("", &r_u, rdata, 0); +/************************************************************************* + get_user_info_21 + *************************************************************************/ +static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid) +{ + NTTIME dummy_time; + struct sam_passwd *sam_pass; + LOGON_HRS hrs; + int i; - if (gids) + if (!pdb_rid_is_user(user_rid)) { - free((char *)gids); + DEBUG(4,("RID 0x%x is not a user RID\n", user_rid)); + return False; } - DEBUG(5,("samr_query_usergroups: %d\n", __LINE__)); + become_root(True); + sam_pass = getsam21pwrid(user_rid); + unbecome_root(True); -} + if (sam_pass == NULL) + { + DEBUG(4,("User 0x%x not found\n", user_rid)); + return False; + } -/******************************************************************* - api_samr_query_usergroups - ********************************************************************/ -static void api_samr_query_usergroups( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_QUERY_USERGROUPS q_u; - samr_io_q_query_usergroups("", &q_u, data, 0); - samr_reply_query_usergroups(&q_u, rdata); -} + DEBUG(3,("User:[%s]\n", sam_pass->smb_name)); + dummy_time.low = 0xffffffff; + dummy_time.high = 0x7fffffff; -/******************************************************************* - opens a samr alias by rid, returns a policy handle. - ********************************************************************/ -static uint32 open_samr_alias(DOM_SID *sid, POLICY_HND *alias_pol, - uint32 alias_rid) -{ - BOOL pol_open = False; - uint32 status = 0x0; + DEBUG(5,("get_user_info_21 - TODO: convert unix times to NTTIMEs\n")); - /* get a (unique) handle. open a policy on it. */ - if (status == 0x0 && !(pol_open = open_policy_hnd(alias_pol))) + /* create a LOGON_HRS structure */ + hrs.len = sam_pass->hours_len; + SMB_ASSERT_ARRAY(hrs.hours, hrs.len); + for (i = 0; i < hrs.len; i++) { - status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + hrs.hours[i] = sam_pass->hours[i]; } - DEBUG(0,("TODO: verify that the alias rid exists\n")); + init_sam_user_info21(id21, - /* associate a RID with the (unique) handle. */ - if (status == 0x0 && !set_policy_samr_rid(alias_pol, alias_rid)) - { - /* oh, whoops. don't know what error message to return, here */ - status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } + &dummy_time, /* logon_time */ + &dummy_time, /* logoff_time */ + &dummy_time, /* kickoff_time */ + &dummy_time, /* pass_last_set_time */ + &dummy_time, /* pass_can_change_time */ + &dummy_time, /* pass_must_change_time */ - sid_append_rid(sid, alias_rid); + sam_pass->smb_name, /* user_name */ + sam_pass->full_name, /* full_name */ + sam_pass->home_dir, /* home_dir */ + sam_pass->dir_drive, /* dir_drive */ + sam_pass->logon_script, /* logon_script */ + sam_pass->profile_path, /* profile_path */ + sam_pass->acct_desc, /* description */ + sam_pass->workstations, /* workstations user can log in from */ + sam_pass->unknown_str, /* don't know, yet */ + sam_pass->munged_dial, /* dialin info. contains dialin path and tel no */ - /* associate an alias SID with the (unique) handle. */ - if (status == 0x0 && !set_policy_samr_sid(alias_pol, sid)) - { - /* oh, whoops. don't know what error message to return, here */ - status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } + sam_pass->user_rid, /* RID user_id */ + sam_pass->group_rid, /* RID group_id */ + sam_pass->acct_ctrl, - if (status != 0 && pol_open) - { - close_policy_hnd(alias_pol); - } + sam_pass->unknown_3, /* unknown_3 */ + sam_pass->logon_divs, /* divisions per week */ + &hrs, /* logon hours */ + sam_pass->unknown_5, + sam_pass->unknown_6); - return status; + return True; } /******************************************************************* - samr_reply_create_dom_alias + samr_reply_query_userinfo ********************************************************************/ -static void samr_reply_create_dom_alias(SAMR_Q_CREATE_DOM_ALIAS *q_u, +static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u, prs_struct *rdata) { - SAMR_R_CREATE_DOM_ALIAS r_u; - DOM_SID dom_sid; - LOCAL_GRP grp; - POLICY_HND alias_pol; - uint32 status = 0x0; + SAMR_R_QUERY_USERINFO r_u; +#if 0 + SAM_USER_INFO_11 id11; +#endif + SAM_USER_INFO_10 id10; + SAM_USER_INFO_21 id21; + void *info = NULL; - bzero(&alias_pol, sizeof(alias_pol)); + uint32 status = 0x0; + uint32 rid = 0x0; - DEBUG(5,("samr_create_dom_alias: %d\n", __LINE__)); + DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__)); - /* find the policy handle. open a policy on it. */ - if (status == 0x0 && (find_policy_by_hnd(&(q_u->dom_pol)) == -1)) + /* search for the handle */ + if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1)) { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + status = NT_STATUS_INVALID_HANDLE; } - /* find the domain sid */ - if (status == 0x0 && !get_policy_samr_sid(&q_u->dom_pol, &dom_sid)) + /* find the user's rid */ + if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff) { - status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; + status = NT_STATUS_OBJECT_TYPE_MISMATCH; } - if (!sid_equal(&dom_sid, &global_sam_sid)) - { - status = 0xC0000000 | NT_STATUS_ACCESS_DENIED; - } + DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid)); + /* ok! user info levels (there are lots: see MSDEV help), off we go... */ if (status == 0x0) { - unistr2_to_ascii(grp.name, &q_u->uni_acct_desc, sizeof(grp.name)-1); - fstrcpy(grp.comment, ""); - grp.rid = 0xffffffff; + switch (q_u->switch_value) + { + case 0x10: + { + info = (void*)&id10; + status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER; + break; + } +#if 0 +/* whoops - got this wrong. i think. or don't understand what's happening. */ + case 0x11: + { + NTTIME expire; + info = (void*)&id11; + + expire.low = 0xffffffff; + expire.high = 0x7fffffff; + + make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080); + + break; + } +#endif + case 21: + { + info = (void*)&id21; + status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER; + break; + } - become_root(True); - status = add_alias_entry(&grp) ? 0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); - unbecome_root(True); - } + default: + { + status = NT_STATUS_INVALID_INFO_CLASS; - if (status == 0x0) - { - status = open_samr_alias(&dom_sid, &alias_pol, grp.rid); + break; + } + } } - /* construct the response. */ - make_samr_r_create_dom_alias(&r_u, &alias_pol, grp.rid, status); + init_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status); /* store the response in the SMB stream */ - samr_io_r_create_dom_alias("", &r_u, rdata, 0); - - DEBUG(5,("samr_create_dom_alias: %d\n", __LINE__)); + samr_io_r_query_userinfo("", &r_u, rdata, 0); -} + DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__)); -/******************************************************************* - api_samr_create_dom_alias - ********************************************************************/ -static void api_samr_create_dom_alias( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_CREATE_DOM_ALIAS q_u; - samr_io_q_create_dom_alias("", &q_u, data, 0); - samr_reply_create_dom_alias(&q_u, rdata); } - /******************************************************************* - opens a samr group by rid, returns a policy handle. + api_samr_query_userinfo ********************************************************************/ -static uint32 open_samr_group(DOM_SID *sid, POLICY_HND *group_pol, - uint32 group_rid) +static BOOL api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata) { - BOOL pol_open = False; - uint32 status = 0x0; - - /* get a (unique) handle. open a policy on it. */ - if (status == 0x0 && !(pol_open = open_policy_hnd(group_pol))) - { - status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - DEBUG(0,("TODO: verify that the group rid exists\n")); - - /* associate a RID with the (unique) handle. */ - if (status == 0x0 && !set_policy_samr_rid(group_pol, group_rid)) - { - /* oh, whoops. don't know what error message to return, here */ - status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - sid_append_rid(sid, group_rid); + SAMR_Q_QUERY_USERINFO q_u; - /* associate an group SID with the (unique) handle. */ - if (status == 0x0 && !set_policy_samr_sid(group_pol, sid)) - { - /* oh, whoops. don't know what error message to return, here */ - status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } + /* grab the samr unknown 24 */ + samr_io_q_query_userinfo("", &q_u, data, 0); - if (status != 0 && pol_open) - { - close_policy_hnd(group_pol); - } + /* construct reply. always indicate success */ + samr_reply_query_userinfo(&q_u, rdata); - return status; + return True; } + /******************************************************************* - samr_reply_create_dom_group + samr_reply_query_usergroups ********************************************************************/ -static void samr_reply_create_dom_group(SAMR_Q_CREATE_DOM_GROUP *q_u, +static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u, prs_struct *rdata) { - SAMR_R_CREATE_DOM_GROUP r_u; - DOM_SID dom_sid; - DOMAIN_GRP grp; - POLICY_HND group_pol; + SAMR_R_QUERY_USERGROUPS r_u; uint32 status = 0x0; - bzero(&group_pol, sizeof(group_pol)); + struct sam_passwd *sam_pass; + DOM_GID *gids = NULL; + int num_groups = 0; + uint32 rid; - DEBUG(5,("samr_create_dom_group: %d\n", __LINE__)); + DEBUG(5,("samr_query_usergroups: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (status == 0x0 && (find_policy_by_hnd(&(q_u->pol)) == -1)) + if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1)) { status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; } - /* find the domain sid */ - if (status == 0x0 && !get_policy_samr_sid(&q_u->pol, &dom_sid)) - { - status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH; - } - - if (!sid_equal(&dom_sid, &global_sam_sid)) + /* find the user's rid */ + if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff) { - status = 0xC0000000 | NT_STATUS_ACCESS_DENIED; + status = NT_STATUS_OBJECT_TYPE_MISMATCH; } if (status == 0x0) { - unistr2_to_ascii(grp.name, &q_u->uni_acct_desc, sizeof(grp.name)-1); - fstrcpy(grp.comment, ""); - grp.rid = 0xffffffff; - grp.attr = 0x07; - become_root(True); - status = add_group_entry(&grp) ? 0x0 : (0xC0000000 | NT_STATUS_ACCESS_DENIED); + sam_pass = getsam21pwrid(rid); unbecome_root(True); + + if (sam_pass == NULL) + { + status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; + } } if (status == 0x0) { - status = open_samr_group(&dom_sid, &group_pol, grp.rid); + pstring groups; + get_domain_user_groups(groups, sam_pass->smb_name); + gids = NULL; + num_groups = make_dom_gids(groups, &gids); } - /* construct the response. */ - make_samr_r_create_dom_group(&r_u, &group_pol, grp.rid, status); + /* construct the response. lkclXXXX: gids are not copied! */ + init_samr_r_query_usergroups(&r_u, num_groups, gids, status); /* store the response in the SMB stream */ - samr_io_r_create_dom_group("", &r_u, rdata, 0); + samr_io_r_query_usergroups("", &r_u, rdata, 0); + + if (gids) + { + free((char *)gids); + } - DEBUG(5,("samr_create_dom_group: %d\n", __LINE__)); + DEBUG(5,("samr_query_usergroups: %d\n", __LINE__)); } /******************************************************************* - api_samr_create_dom_group + api_samr_query_usergroups ********************************************************************/ -static void api_samr_create_dom_group( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_query_usergroups( uint16 vuid, prs_struct *data, prs_struct *rdata) { - SAMR_Q_CREATE_DOM_GROUP q_u; - samr_io_q_create_dom_group("", &q_u, data, 0); - samr_reply_create_dom_group(&q_u, rdata); + SAMR_Q_QUERY_USERGROUPS q_u; + /* grab the samr unknown 32 */ + samr_io_q_query_usergroups("", &q_u, data, 0); + + /* construct reply. */ + samr_reply_query_usergroups(&q_u, rdata); + + return True; } @@ -2664,7 +1386,7 @@ static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u, DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (r_u.status == 0x0 && (find_policy_by_hnd(&(q_u->domain_pol)) == -1)) + if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1)) { r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; DEBUG(5,("samr_reply_query_dom_info: invalid handle\n")); @@ -2674,38 +1396,10 @@ static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u, { switch (q_u->switch_value) { - case 0x07: - { - switch_value = 0x7; - make_unk_info7(&ctr.info.inf7); - - break; - } - case 0x06: - { - switch_value = 0x6; - make_unk_info6(&ctr.info.inf6); - - break; - } - case 0x03: - { - switch_value = 0x3; - make_unk_info3(&ctr.info.inf3); - - break; - } case 0x02: { switch_value = 0x2; - make_unk_info2(&ctr.info.inf2, global_sam_name, global_myname); - - break; - } - case 0x01: - { - switch_value = 0x1; - make_unk_info1(&ctr.info.inf1); + init_unk_info2(&ctr.info.inf2, global_myworkgroup, global_myname); break; } @@ -2717,7 +1411,7 @@ static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u, } } - make_samr_r_query_dom_info(&r_u, switch_value, &ctr, status); + init_samr_r_query_dom_info(&r_u, switch_value, &ctr, status); /* store the response in the SMB stream */ samr_io_r_query_dom_info("", &r_u, rdata, 0); @@ -2729,123 +1423,96 @@ static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u, /******************************************************************* api_samr_query_dom_info ********************************************************************/ -static void api_samr_query_dom_info( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct *rdata) { SAMR_Q_QUERY_DOMAIN_INFO q_e; + + /* grab the samr unknown 8 command */ samr_io_q_query_dom_info("", &q_e, data, 0); + + /* construct reply. */ samr_reply_query_dom_info(&q_e, rdata); + + return True; } /******************************************************************* - samr_reply_create_user + samr_reply_unknown_32 ********************************************************************/ -static void samr_reply_create_user(SAMR_Q_CREATE_USER *q_u, - prs_struct *rdata) +static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u, + prs_struct *rdata, + int status) { - struct sam_passwd *sam_pass; - fstring user_name; - - SAMR_R_CREATE_USER r_u; - POLICY_HND pol; - uint32 status = 0x0; - uint32 user_rid = 0x0; - BOOL pol_open = False; - uint32 unk_0 = 0x30; - - /* find the machine account: tell the caller if it exists. - lkclXXXX i have *no* idea if this is a problem or not - or even if you are supposed to construct a different - reply if the account already exists... - */ - - /* find the policy handle. open a policy on it. */ - if (status == 0x0 && (find_policy_by_hnd(&(q_u->domain_pol)) == -1)) - { - status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - - /* get a (unique) handle. open a policy on it. */ - if (status == 0x0 && !(pol_open = open_policy_hnd(&pol))) - { - status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - unistr2_to_ascii(user_name, &q_u->uni_name, sizeof(user_name)-1); - - sam_pass = getsam21pwntnam(user_name); + int i; + SAMR_R_UNKNOWN_32 r_u; - if (sam_pass != NULL) - { - /* account exists: say so */ - status = 0xC0000000 | NT_STATUS_USER_EXISTS; - } - else + /* set up the SAMR unknown_32 response */ + memset((char *)r_u.pol.data, '\0', POL_HND_SIZE); + if (status == 0) { - pstring err_str; - pstring msg_str; - - if (!local_password_change(user_name, True, - q_u->acb_info | ACB_DISABLED | ACB_PWNOTREQ, 0xffff, - NULL, - err_str, sizeof(err_str), - msg_str, sizeof(msg_str))) - { - DEBUG(0,("%s\n", err_str)); - status = 0xC0000000 | NT_STATUS_ACCESS_DENIED; - } - else + for (i = 4; i < POL_HND_SIZE; i++) { - sam_pass = getsam21pwntnam(user_name); - if (sam_pass == NULL) - { - /* account doesn't exist: say so */ - status = 0xC0000000 | NT_STATUS_ACCESS_DENIED; - } - else - { - user_rid = sam_pass->user_rid; - unk_0 = 0x000703ff; - } + r_u.pol.data[i] = i+1; } } - /* associate the RID with the (unique) handle. */ - if (status == 0x0 && !set_policy_samr_rid(&pol, user_rid)) - { - /* oh, whoops. don't know what error message to return, here */ - status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - if (status != 0 && pol_open) - { - close_policy_hnd(&pol); - } - - DEBUG(5,("samr_create_user: %d\n", __LINE__)); + init_dom_rid4(&(r_u.rid4), 0x0030, 0, 0); + r_u.status = status; - make_samr_r_create_user(&r_u, &pol, unk_0, user_rid, status); + DEBUG(5,("samr_unknown_32: %d\n", __LINE__)); /* store the response in the SMB stream */ - samr_io_r_create_user("", &r_u, rdata, 0); + samr_io_r_unknown_32("", &r_u, rdata, 0); - DEBUG(5,("samr_create_user: %d\n", __LINE__)); + DEBUG(5,("samr_unknown_32: %d\n", __LINE__)); } /******************************************************************* - api_samr_create_user + api_samr_unknown_32 ********************************************************************/ -static void api_samr_create_user( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdata) { - SAMR_Q_CREATE_USER q_u; + uint32 status = 0; + struct sam_passwd *sam_pass; + fstring mach_acct; + + SAMR_Q_UNKNOWN_32 q_u; /* grab the samr unknown 32 */ - samr_io_q_create_user("", &q_u, data, 0); + samr_io_q_unknown_32("", &q_u, data, 0); + + /* find the machine account: tell the caller if it exists. + lkclXXXX i have *no* idea if this is a problem or not + or even if you are supposed to construct a different + reply if the account already exists... + */ + + fstrcpy(mach_acct, dos_unistrn2(q_u.uni_mach_acct.buffer, + q_u.uni_mach_acct.uni_str_len)); + + become_root(True); + sam_pass = getsam21pwnam(mach_acct); + unbecome_root(True); + + if (sam_pass != NULL) + { + /* machine account exists: say so */ + status = 0xC0000000 | NT_STATUS_USER_EXISTS; + } + else + { + /* this could cause trouble... */ + DEBUG(0,("trouble!\n")); + status = 0; + } /* construct reply. */ - samr_reply_create_user(&q_u, rdata); + samr_reply_unknown_32(&q_u, rdata, status); + + return True; } @@ -2862,13 +1529,13 @@ static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u, r_u.status = 0x0; /* get a (unique) handle. open a policy on it. */ - if (r_u.status == 0x0 && !(pol_open = open_policy_hnd(&(r_u.connect_pol)))) + if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol)))) { r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; } /* associate the domain SID with the (unique) handle. */ - if (r_u.status == 0x0 && !set_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0)) + if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0)) { /* oh, whoops. don't know what error message to return, here */ r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -2876,7 +1543,7 @@ static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u, if (r_u.status != 0 && pol_open) { - close_policy_hnd(&(r_u.connect_pol)); + close_lsa_policy_hnd(&(r_u.connect_pol)); } DEBUG(5,("samr_connect_anon: %d\n", __LINE__)); @@ -2891,11 +1558,17 @@ static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u, /******************************************************************* api_samr_connect_anon ********************************************************************/ -static void api_samr_connect_anon( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_connect_anon( uint16 vuid, prs_struct *data, prs_struct *rdata) { SAMR_Q_CONNECT_ANON q_u; + + /* grab the samr open policy */ samr_io_q_connect_anon("", &q_u, data, 0); + + /* construct reply. always indicate success */ samr_reply_connect_anon(&q_u, rdata); + + return True; } /******************************************************************* @@ -2911,13 +1584,13 @@ static void samr_reply_connect(SAMR_Q_CONNECT *q_u, r_u.status = 0x0; /* get a (unique) handle. open a policy on it. */ - if (r_u.status == 0x0 && !(pol_open = open_policy_hnd(&(r_u.connect_pol)))) + if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol)))) { r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; } /* associate the domain SID with the (unique) handle. */ - if (r_u.status == 0x0 && !set_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0)) + if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0)) { /* oh, whoops. don't know what error message to return, here */ r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -2925,7 +1598,7 @@ static void samr_reply_connect(SAMR_Q_CONNECT *q_u, if (r_u.status != 0 && pol_open) { - close_policy_hnd(&(r_u.connect_pol)); + close_lsa_policy_hnd(&(r_u.connect_pol)); } DEBUG(5,("samr_connect: %d\n", __LINE__)); @@ -2940,11 +1613,17 @@ static void samr_reply_connect(SAMR_Q_CONNECT *q_u, /******************************************************************* api_samr_connect ********************************************************************/ -static void api_samr_connect( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_connect( uint16 vuid, prs_struct *data, prs_struct *rdata) { SAMR_Q_CONNECT q_u; + + /* grab the samr open policy */ samr_io_q_connect("", &q_u, data, 0); + + /* construct reply. always indicate success */ samr_reply_connect(&q_u, rdata); + + return True; } /******************************************************************* @@ -2954,36 +1633,19 @@ static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u, prs_struct *rdata) { SAMR_R_OPEN_ALIAS r_u; - DOM_SID sid; BOOL pol_open = False; /* set up the SAMR open_alias response */ r_u.status = 0x0; - if (r_u.status == 0x0 && !get_policy_samr_sid(&q_u->dom_pol, &sid)) - { - r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - /* get a (unique) handle. open a policy on it. */ - if (r_u.status == 0x0 && !(pol_open = open_policy_hnd(&(r_u.pol)))) + if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol)))) { r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; } - DEBUG(0,("TODO: verify that the alias rid exists\n")); - /* associate a RID with the (unique) handle. */ - if (r_u.status == 0x0 && !set_policy_samr_rid(&(r_u.pol), q_u->rid_alias)) - { - /* oh, whoops. don't know what error message to return, here */ - r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - - sid_append_rid(&sid, q_u->rid_alias); - - /* associate an alias SID with the (unique) handle. */ - if (r_u.status == 0x0 && !set_policy_samr_sid(&(r_u.pol), &sid)) + if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias)) { /* oh, whoops. don't know what error message to return, here */ r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -2991,7 +1653,7 @@ static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u, if (r_u.status != 0 && pol_open) { - close_policy_hnd(&(r_u.pol)); + close_lsa_policy_hnd(&(r_u.pol)); } DEBUG(5,("samr_open_alias: %d\n", __LINE__)); @@ -3006,117 +1668,18 @@ static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u, /******************************************************************* api_samr_open_alias ********************************************************************/ -static void api_samr_open_alias( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) +static BOOL api_samr_open_alias( uint16 vuid, prs_struct *data, prs_struct *rdata) { SAMR_Q_OPEN_ALIAS q_u; - samr_io_q_open_alias("", &q_u, data, 0); - samr_reply_open_alias(&q_u, rdata); -} - -/******************************************************************* - samr_reply_open_group - ********************************************************************/ -static void samr_reply_open_group(SAMR_Q_OPEN_GROUP *q_u, - prs_struct *rdata) -{ - SAMR_R_OPEN_GROUP r_u; - DOM_SID sid; - - DEBUG(5,("samr_open_group: %d\n", __LINE__)); - - r_u.status = 0x0; - - /* find the domain sid associated with the policy handle */ - if (r_u.status == 0x0 && !get_policy_samr_sid(&q_u->domain_pol, &sid)) - { - r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - - if (r_u.status == 0x0 && !sid_equal(&sid, &global_sam_sid)) - { - r_u.status = 0xC0000000 | NT_STATUS_ACCESS_DENIED; - } - - if (r_u.status == 0x0) - { - r_u.status = open_samr_group(&sid, &r_u.pol, q_u->rid_group); - } - - /* store the response in the SMB stream */ - samr_io_r_open_group("", &r_u, rdata, 0); - - DEBUG(5,("samr_open_group: %d\n", __LINE__)); - -} - -/******************************************************************* - api_samr_open_group - ********************************************************************/ -static void api_samr_open_group( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) - -{ - SAMR_Q_OPEN_GROUP q_u; - samr_io_q_open_group("", &q_u, data, 0); - samr_reply_open_group(&q_u, rdata); -} - -/******************************************************************* - samr_reply_lookup_domain - ********************************************************************/ -static void samr_reply_lookup_domain(SAMR_Q_LOOKUP_DOMAIN *q_u, - prs_struct *rdata) -{ - SAMR_R_LOOKUP_DOMAIN r_u; - fstring domain; - - DEBUG(5,("samr_lookup_domain: %d\n", __LINE__)); - - r_u.ptr_sid = 0; - r_u.status = 0x0; - - /* find the connection policy handle */ - if (find_policy_by_hnd(&(q_u->connect_pol)) == -1) - { - r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; - } - - if (r_u.status == 0x0) - { - unistr2_to_ascii(domain, &(q_u->uni_domain), sizeof(domain)); - DEBUG(5, ("Lookup Domain: %s\n", domain)); - - /* check it's one of ours */ - if (strequal(domain, global_sam_name)) - { - make_dom_sid2(&(r_u.dom_sid), &global_sam_sid); - r_u.ptr_sid = 1; - } - else if (strequal(domain, "BUILTIN")) - { - make_dom_sid2(&(r_u.dom_sid), &global_sid_S_1_5_20); - r_u.ptr_sid = 1; - } - else - { - r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_DOMAIN; - } - } - /* store the response in the SMB stream */ - samr_io_r_lookup_domain("", &r_u, rdata, 0); + /* grab the samr open policy */ + samr_io_q_open_alias("", &q_u, data, 0); - DEBUG(5,("samr_lookup_domain: %d\n", __LINE__)); -} + /* construct reply. always indicate success */ + samr_reply_open_alias(&q_u, rdata); -/******************************************************************* - api_samr_lookup_domain - ********************************************************************/ -static void api_samr_lookup_domain( rpcsrv_struct *p, prs_struct *data, prs_struct *rdata) -{ - SAMR_Q_LOOKUP_DOMAIN q_u; - samr_io_q_lookup_domain("", &q_u, data, 0); - samr_reply_lookup_domain(&q_u, rdata); + return True; } /******************************************************************* @@ -3127,51 +1690,32 @@ static struct api_struct api_samr_cmds [] = { "SAMR_CLOSE_HND" , SAMR_CLOSE_HND , api_samr_close_hnd }, { "SAMR_CONNECT" , SAMR_CONNECT , api_samr_connect }, { "SAMR_CONNECT_ANON" , SAMR_CONNECT_ANON , api_samr_connect_anon }, - { "SAMR_ENUM_DOMAINS" , SAMR_ENUM_DOMAINS , api_samr_enum_domains }, { "SAMR_ENUM_DOM_USERS" , SAMR_ENUM_DOM_USERS , api_samr_enum_dom_users }, { "SAMR_ENUM_DOM_GROUPS" , SAMR_ENUM_DOM_GROUPS , api_samr_enum_dom_groups }, { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases }, - { "SAMR_QUERY_USERALIASES", SAMR_QUERY_USERALIASES, api_samr_query_useraliases}, - { "SAMR_QUERY_ALIASMEM" , SAMR_QUERY_ALIASMEM , api_samr_query_aliasmem }, - { "SAMR_QUERY_GROUPMEM" , SAMR_QUERY_GROUPMEM , api_samr_query_groupmem }, - { "SAMR_ADD_ALIASMEM" , SAMR_ADD_ALIASMEM , api_samr_add_aliasmem }, - { "SAMR_DEL_ALIASMEM" , SAMR_DEL_ALIASMEM , api_samr_del_aliasmem }, - { "SAMR_ADD_GROUPMEM" , SAMR_ADD_GROUPMEM , api_samr_add_groupmem }, - { "SAMR_DEL_GROUPMEM" , SAMR_DEL_GROUPMEM , api_samr_del_groupmem }, - { "SAMR_DELETE_DOM_GROUP" , SAMR_DELETE_DOM_GROUP , api_samr_delete_dom_group }, - { "SAMR_DELETE_DOM_ALIAS" , SAMR_DELETE_DOM_ALIAS , api_samr_delete_dom_alias }, - { "SAMR_CREATE_DOM_GROUP" , SAMR_CREATE_DOM_GROUP , api_samr_create_dom_group }, - { "SAMR_CREATE_DOM_ALIAS" , SAMR_CREATE_DOM_ALIAS , api_samr_create_dom_alias }, + { "SAMR_LOOKUP_IDS" , SAMR_LOOKUP_IDS , api_samr_lookup_ids }, { "SAMR_LOOKUP_NAMES" , SAMR_LOOKUP_NAMES , api_samr_lookup_names }, { "SAMR_OPEN_USER" , SAMR_OPEN_USER , api_samr_open_user }, { "SAMR_QUERY_USERINFO" , SAMR_QUERY_USERINFO , api_samr_query_userinfo }, - { "SAMR_SET_USERINFO" , SAMR_SET_USERINFO , api_samr_set_userinfo }, - { "SAMR_SET_USERINFO2" , SAMR_SET_USERINFO2 , api_samr_set_userinfo2 }, - { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info }, + { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info }, { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups }, { "SAMR_QUERY_DISPINFO" , SAMR_QUERY_DISPINFO , api_samr_query_dispinfo }, - { "SAMR_QUERY_DISPINFO3" , SAMR_QUERY_DISPINFO3 , api_samr_query_dispinfo }, - { "SAMR_QUERY_DISPINFO4" , SAMR_QUERY_DISPINFO4 , api_samr_query_dispinfo }, { "SAMR_QUERY_ALIASINFO" , SAMR_QUERY_ALIASINFO , api_samr_query_aliasinfo }, - { "SAMR_QUERY_GROUPINFO" , SAMR_QUERY_GROUPINFO , api_samr_query_groupinfo }, - { "SAMR_CREATE_USER" , SAMR_CREATE_USER , api_samr_create_user }, - { "SAMR_LOOKUP_RIDS" , SAMR_LOOKUP_RIDS , api_samr_lookup_rids }, - { "SAMR_GET_DOM_PWINFO" , SAMR_GET_DOM_PWINFO , api_samr_unknown_38 }, + { "SAMR_0x32" , 0x32 , api_samr_unknown_32 }, + { "SAMR_UNKNOWN_12" , SAMR_UNKNOWN_12 , api_samr_unknown_12 }, + { "SAMR_UNKNOWN_38" , SAMR_UNKNOWN_38 , api_samr_unknown_38 }, { "SAMR_CHGPASSWD_USER" , SAMR_CHGPASSWD_USER , api_samr_chgpasswd_user }, { "SAMR_OPEN_ALIAS" , SAMR_OPEN_ALIAS , api_samr_open_alias }, - { "SAMR_OPEN_GROUP" , SAMR_OPEN_GROUP , api_samr_open_group }, { "SAMR_OPEN_DOMAIN" , SAMR_OPEN_DOMAIN , api_samr_open_domain }, - { "SAMR_LOOKUP_DOMAIN" , SAMR_LOOKUP_DOMAIN , api_samr_lookup_domain }, - { "SAMR_QUERY_SEC_OBJECT" , SAMR_QUERY_SEC_OBJECT , api_samr_unknown_3 }, - { "SAMR_GET_USRDOM_PWINFO", SAMR_GET_USRDOM_PWINFO, api_samr_unknown_2c }, + { "SAMR_UNKNOWN_3" , SAMR_UNKNOWN_3 , api_samr_unknown_3 }, + { "SAMR_UNKNOWN_2C" , SAMR_UNKNOWN_2C , api_samr_unknown_2c }, { NULL , 0 , NULL } }; /******************************************************************* receives a samr pipe and responds. ********************************************************************/ -BOOL api_samr_rpc(rpcsrv_struct *p, prs_struct *data) +BOOL api_samr_rpc(pipes_struct *p, prs_struct *data) { return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data); } - diff --git a/source3/rpc_server/srv_srvsvc.c b/source3/rpc_server/srv_srvsvc.c index 8dd99cccc6..f42b94832b 100644 --- a/source3/rpc_server/srv_srvsvc.c +++ b/source3/rpc_server/srv_srvsvc.c @@ -30,248 +30,253 @@ extern int DEBUGLEVEL; extern pstring global_myname; /******************************************************************* - fill in a share info level 1 structure. + Fill in a share info level 1 structure. + ********************************************************************/ - this function breaks the rule that i'd like to be in place, namely - it doesn't receive its data as arguments: it has to call lp_xxxx() - functions itself. yuck. +static void init_srv_share_info_1(SRV_SHARE_INFO_1 *sh1, int snum) +{ + int len_net_name; + pstring net_name; + pstring remark; + uint32 type; - see ipc.c:fill_share_info() + pstrcpy(net_name, lp_servicename(snum)); + pstrcpy(remark, lp_comment(snum)); + pstring_sub(remark,"%S",lp_servicename(snum)); + len_net_name = strlen(net_name); + /* work out the share type */ + type = STYPE_DISKTREE; + + if (lp_print_ok(snum)) + type = STYPE_PRINTQ; + if (strequal("IPC$", net_name)) + type = STYPE_IPC; + if (net_name[len_net_name] == '$') + type |= STYPE_HIDDEN; + + init_srv_share_info1(&sh1->info_1, net_name, type, remark); + init_srv_share_info1_str(&sh1->info_1_str, net_name, remark); +} + +/******************************************************************* + Fill in a share info level 2 structure. ********************************************************************/ -static void make_srv_share_1_info(SH_INFO_1 *sh1, - SH_INFO_1_STR *str1, int snum) + +static void init_srv_share_info_2(SRV_SHARE_INFO_2 *sh2, int snum) { int len_net_name; pstring net_name; pstring remark; + pstring path; + pstring passwd; uint32 type; pstrcpy(net_name, lp_servicename(snum)); - pstrcpy(remark , lp_comment (snum)); + pstrcpy(remark, lp_comment(snum)); + pstring_sub(remark,"%S",lp_servicename(snum)); + pstrcpy(path, lp_pathname(snum)); + pstrcpy(passwd, ""); len_net_name = strlen(net_name); /* work out the share type */ type = STYPE_DISKTREE; - if (lp_print_ok(snum)) type = STYPE_PRINTQ; - if (strequal("IPC$", net_name)) type = STYPE_IPC; - if (net_name[len_net_name] == '$') type |= STYPE_HIDDEN; - - make_srv_share_info1 (sh1 , net_name, type, remark); - make_srv_share_info1_str(str1, net_name, remark); + if (lp_print_ok(snum)) + type = STYPE_PRINTQ; + if (strequal("IPC$", net_name)) + type = STYPE_IPC; + if (net_name[len_net_name] == '$') + type |= STYPE_HIDDEN; + + init_srv_share_info2(&sh2->info_2, net_name, type, remark, 0, 0xffffffff, 1, path, passwd); + init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd); } /******************************************************************* - fill in a share info level 1 structure. - - this function breaks the rule that i'd like to be in place, namely - it doesn't receive its data as arguments: it has to call lp_xxxx() - functions itself. yuck. - + Fill in a share info structure. ********************************************************************/ -static void make_srv_share_info_1(SRV_SHARE_INFO_1 *sh1, uint32 *snum, uint32 *svcs) + +static BOOL init_srv_share_info_ctr(SRV_SHARE_INFO_CTR *ctr, + uint32 info_level, uint32 *resume_hnd, uint32 *total_entries) { - uint32 num_entries = 0; - (*svcs) = lp_numservices(); + int num_entries = 0; + int num_services = lp_numservices(); + int snum; - if (sh1 == NULL) - { - (*snum) = 0; - return; + DEBUG(5,("init_srv_share_info_ctr\n")); + + ZERO_STRUCTPN(ctr); + + ctr->info_level = ctr->switch_value = info_level; + *resume_hnd = 0; + + /* Count the number of entries. */ + for (snum = 0; snum < num_services; snum++) { + if (lp_browseable(snum) && lp_snum_ok(snum)) + num_entries++; } - DEBUG(5,("make_srv_share_1_sh1\n")); + *total_entries = num_entries; + ctr->num_entries2 = ctr->num_entries = num_entries; + ctr->ptr_share_info = ctr->ptr_entries = 1; - for (; (*snum) < (*svcs) && num_entries < MAX_SHARE_ENTRIES; (*snum)++) + if (!num_entries) + return True; + + switch (info_level) { + case 1: { - if (lp_browseable((*snum)) && lp_snum_ok((*snum))) - { - make_srv_share_1_info(&(sh1->info_1 [num_entries]), - &(sh1->info_1_str[num_entries]), (*snum)); + SRV_SHARE_INFO_1 *info1; + int i = 0; - /* move on to creating next share */ - num_entries++; + info1 = malloc(num_entries * sizeof(SRV_SHARE_INFO_1)); + + for (snum = *resume_hnd; snum < num_services; snum++) { + if (lp_browseable(snum) && lp_snum_ok(snum)) { + init_srv_share_info_1(&info1[i++], snum); + } } + + ctr->share.info1 = info1; + break; } - sh1->num_entries_read = num_entries; - sh1->ptr_share_info = num_entries > 0 ? 1 : 0; - sh1->num_entries_read2 = num_entries; - - if ((*snum) >= (*svcs)) + case 2: { - (*snum) = 0; + SRV_SHARE_INFO_2 *info2; + int i = 0; + + info2 = malloc(num_entries * sizeof(SRV_SHARE_INFO_2)); + + for (snum = *resume_hnd; snum < num_services; snum++) { + if (lp_browseable(snum) && lp_snum_ok(snum)) { + init_srv_share_info_2(&info2[i++], snum); + } + } + + ctr->share.info2 = info2; + break; } -} -/******************************************************************* - fill in a share info level 2 structure. + default: + DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n", info_level)); + return False; + } - this function breaks the rule that i'd like to be in place, namely - it doesn't receive its data as arguments: it has to call lp_xxxx() - functions itself. yuck. + return True; +} - see ipc.c:fill_share_info() +/******************************************************************* + Inits a SRV_R_NET_SHARE_ENUM structure. +********************************************************************/ - ********************************************************************/ -static void make_srv_share_2_info(SH_INFO_2 *sh2, - SH_INFO_2_STR *str2, int snum) +static void init_srv_r_net_share_enum(SRV_R_NET_SHARE_ENUM *r_n, + uint32 info_level, uint32 resume_hnd) { - int len_net_name; - pstring net_name; - pstring remark; - pstring path; - pstring passwd; - uint32 type; + DEBUG(5,("init_srv_r_net_share_enum: %d\n", __LINE__)); - pstrcpy(net_name, lp_servicename(snum)); - pstrcpy(remark , lp_comment (snum)); - pstrcpy(path , lp_pathname (snum)); - pstrcpy(passwd , ""); - len_net_name = strlen(net_name); - - /* work out the share type */ - type = STYPE_DISKTREE; - - if (lp_print_ok(snum)) type = STYPE_PRINTQ; - if (strequal("IPC$", net_name)) type = STYPE_IPC; - if (net_name[len_net_name] == '$') type |= STYPE_HIDDEN; + if (init_srv_share_info_ctr(&r_n->ctr, info_level, + &resume_hnd, &r_n->total_entries)) { + r_n->status = 0x0; + } else { + r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + } - make_srv_share_info2 (sh2 , net_name, type, remark, 0, 0xffffffff, 1, path, passwd); - make_srv_share_info2_str(str2, net_name, remark, path, passwd); + init_enum_hnd(&r_n->enum_hnd, resume_hnd); } /******************************************************************* - fill in a share info level 2 structure. - - this function breaks the rule that i'd like to be in place, namely - it doesn't receive its data as arguments: it has to call lp_xxxx() - functions itself. yuck. + Net share enum. +********************************************************************/ - ********************************************************************/ -static void make_srv_share_info_2(SRV_SHARE_INFO_2 *sh2, uint32 *snum, uint32 *svcs) +static BOOL srv_reply_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n, + prs_struct *rdata) { - uint32 num_entries = 0; - (*svcs) = lp_numservices(); + SRV_R_NET_SHARE_ENUM r_n; + BOOL ret; - if (sh2 == NULL) - { - (*snum) = 0; - return; - } + DEBUG(5,("srv_net_share_enum: %d\n", __LINE__)); - DEBUG(5,("make_srv_share_2_sh1\n")); + /* Create the list of shares for the response. */ + init_srv_r_net_share_enum(&r_n, + q_n->ctr.info_level, + get_enum_hnd(&q_n->enum_hnd)); - for (; (*snum) < (*svcs) && num_entries < MAX_SHARE_ENTRIES; (*snum)++) - { - if (lp_browseable((*snum)) && lp_snum_ok((*snum))) - { - make_srv_share_2_info(&(sh2->info_2 [num_entries]), - &(sh2->info_2_str[num_entries]), (*snum)); + /* store the response in the SMB stream */ + ret = srv_io_r_net_share_enum("", &r_n, rdata, 0); - /* move on to creating next share */ - num_entries++; - } - } + /* Free the memory used by the response. */ + free_srv_r_net_share_enum(&r_n); - sh2->num_entries_read = num_entries; - sh2->ptr_share_info = num_entries > 0 ? 1 : 0; - sh2->num_entries_read2 = num_entries; - - if ((*snum) >= (*svcs)) - { - (*snum) = 0; - } + DEBUG(5,("srv_net_share_enum: %d\n", __LINE__)); + + return ret; } /******************************************************************* - makes a SRV_R_NET_SHARE_ENUM structure. + Inits a SRV_R_NET_SHARE_GET_INFO structure. ********************************************************************/ -static uint32 make_srv_share_info_ctr(SRV_SHARE_INFO_CTR *ctr, - int switch_value, uint32 *resume_hnd, uint32 *total_entries) + +static void init_srv_r_net_share_get_info(SRV_R_NET_SHARE_GET_INFO *r_n, + char *share_name, uint32 info_level) { uint32 status = 0x0; - DEBUG(5,("make_srv_share_info_ctr: %d\n", __LINE__)); + int snum; - ctr->switch_value = switch_value; + DEBUG(5,("init_srv_r_net_share_get_info: %d\n", __LINE__)); - switch (switch_value) - { + r_n->switch_value = info_level; + + snum = find_service(share_name); + + if (snum >= 0) { + switch (info_level) { case 1: - { - make_srv_share_info_1(&(ctr->share.info1), resume_hnd, total_entries); - ctr->ptr_share_ctr = 1; + init_srv_share_info_1(&r_n->share.info1, snum); break; - } case 2: - { - make_srv_share_info_2(&(ctr->share.info2), resume_hnd, total_entries); - ctr->ptr_share_ctr = 2; + init_srv_share_info_2(&r_n->share.info2, snum); break; - } default: - { - DEBUG(5,("make_srv_share_info_ctr: unsupported switch value %d\n", - switch_value)); - (*resume_hnd = 0); - (*total_entries) = 0; - ctr->ptr_share_ctr = 0; + DEBUG(5,("init_srv_net_share_get_info: unsupported switch value %d\n", info_level)); status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; break; } + } else { + status = 0xC0000000 | NT_STATUS_BAD_NETWORK_NAME; } - return status; + r_n->ptr_share_ctr = (status == 0x0) ? 1 : 0; + r_n->status = status; } /******************************************************************* - makes a SRV_R_NET_SHARE_ENUM structure. + Net share get info. ********************************************************************/ -static void make_srv_r_net_share_enum(SRV_R_NET_SHARE_ENUM *r_n, - uint32 resume_hnd, int share_level, int switch_value) -{ - DEBUG(5,("make_srv_r_net_share_enum: %d\n", __LINE__)); - - r_n->share_level = share_level; - if (share_level == 0) - { - r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; - } - else - { - r_n->status = make_srv_share_info_ctr(r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries)); - } - if (r_n->status != 0x0) - { - resume_hnd = 0; - } - make_enum_hnd(&(r_n->enum_hnd), resume_hnd); -} -/******************************************************************* -net share enum -********************************************************************/ -static void srv_reply_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n, - prs_struct *rdata) +static BOOL srv_reply_net_share_get_info(SRV_Q_NET_SHARE_GET_INFO *q_n, + prs_struct *rdata) { - SRV_R_NET_SHARE_ENUM r_n; - SRV_SHARE_INFO_CTR ctr; + SRV_R_NET_SHARE_GET_INFO r_n; + char *share_name; + BOOL ret; - r_n.ctr = &ctr; + DEBUG(5,("srv_net_share_get_info: %d\n", __LINE__)); - DEBUG(5,("srv_net_share_enum: %d\n", __LINE__)); - - /* set up the */ - make_srv_r_net_share_enum(&r_n, - get_enum_hnd(&q_n->enum_hnd), - q_n->share_level, - q_n->ctr->switch_value); + /* Create the list of shares for the response. */ + share_name = dos_unistr2_to_str(&q_n->uni_share_name); + init_srv_r_net_share_get_info(&r_n, share_name, q_n->info_level); /* store the response in the SMB stream */ - srv_io_r_net_share_enum("", &r_n, rdata, 0); + ret = srv_io_r_net_share_get_info("", &r_n, rdata, 0); - DEBUG(5,("srv_net_share_enum: %d\n", __LINE__)); + /* Free the memory used by the response. */ + free_srv_r_net_share_get_info(&r_n); + + DEBUG(5,("srv_net_share_get_info: %d\n", __LINE__)); + + return ret; } /******************************************************************* @@ -282,11 +287,11 @@ static void srv_reply_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n, functions itself. yuck. ********************************************************************/ -static void make_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, +static void init_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, char *name) { - make_srv_sess_info0 (se0 , name); - make_srv_sess_info0_str(str0, name); + init_srv_sess_info0 (se0 , name); + init_srv_sess_info0_str(str0, name); } /******************************************************************* @@ -297,39 +302,26 @@ static void make_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, functions itself. yuck. ********************************************************************/ -static void make_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *stot) +static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *stot) { uint32 num_entries = 0; - struct connect_record *crec; - uint32 session_count; + (*stot) = 1; - if (!get_session_count(&crec, &session_count)) - { - (*snum) = 0; - (*stot) = 0; - return; - } - - (*stot) = session_count; - - DEBUG(0,("Session Count : %u\n",session_count)); - if (ss0 == NULL) { (*snum) = 0; - free(crec); return; } + DEBUG(5,("init_srv_sess_0_ss0\n")); + if (snum) { - DEBUG(0,("snum ok\n")); for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) { - make_srv_sess_0_info(&(ss0->info_0 [num_entries]), - &(ss0->info_0_str[num_entries]), crec[num_entries].machine); + init_srv_sess_0_info(&(ss0->info_0 [num_entries]), + &(ss0->info_0_str[num_entries]), "MACHINE"); - DEBUG(0,("make_srv_sess_0_info\n")); /* move on to creating next session */ /* move on to creating next sess */ num_entries++; @@ -350,7 +342,6 @@ static void make_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto ss0->ptr_sess_info = 0; ss0->num_entries_read2 = 0; } - free(crec); } /******************************************************************* @@ -361,14 +352,14 @@ static void make_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto functions itself. yuck. ********************************************************************/ -static void make_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1, +static void init_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1, char *name, char *user, uint32 num_opens, uint32 open_time, uint32 idle_time, uint32 usr_flgs) { - make_srv_sess_info1 (se1 , name, user, num_opens, open_time, idle_time, usr_flgs); - make_srv_sess_info1_str(str1, name, user); + init_srv_sess_info1 (se1 , name, user, num_opens, open_time, idle_time, usr_flgs); + init_srv_sess_info1_str(str1, name, user); } /******************************************************************* @@ -379,41 +370,26 @@ static void make_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1, functions itself. yuck. ********************************************************************/ -static void make_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *stot) +static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *stot) { uint32 num_entries = 0; - struct connect_record *crec; - uint32 session_count; + (*stot) = 1; - if (!get_session_count(&crec, &session_count)) - { - (*snum) = 0; - (*stot) = 0; - return; - } - - (*stot) = session_count; - - DEBUG(0,("Session Count (info1) : %u\n",session_count)); if (ss1 == NULL) { (*snum) = 0; - free(crec); return; } - DEBUG(5,("make_srv_sess_1_ss1\n")); + DEBUG(5,("init_srv_sess_1_ss1\n")); if (snum) { for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) { - DEBUG(0,("sess1 machine: %s, uid : %u\n",crec[num_entries].machine,crec[num_entries].uid)); - make_srv_sess_1_info(&(ss1->info_1 [num_entries]), + init_srv_sess_1_info(&(ss1->info_1 [num_entries]), &(ss1->info_1_str[num_entries]), - crec[num_entries].machine, - uidtoname(crec[num_entries].uid), 1, 10, 5, 0); -/* What are these on the End ??? */ + "MACHINE", "dummy_user", 1, 10, 5, 0); /* move on to creating next session */ /* move on to creating next sess */ @@ -437,17 +413,16 @@ static void make_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *sto (*stot) = 0; } - free(crec); } /******************************************************************* makes a SRV_R_NET_SESS_ENUM structure. ********************************************************************/ -static uint32 make_srv_sess_info_ctr(SRV_SESS_INFO_CTR *ctr, +static uint32 init_srv_sess_info_ctr(SRV_SESS_INFO_CTR *ctr, int switch_value, uint32 *resume_hnd, uint32 *total_entries) { uint32 status = 0x0; - DEBUG(5,("make_srv_sess_info_ctr: %d\n", __LINE__)); + DEBUG(5,("init_srv_sess_info_ctr: %d\n", __LINE__)); ctr->switch_value = switch_value; @@ -455,19 +430,19 @@ static uint32 make_srv_sess_info_ctr(SRV_SESS_INFO_CTR *ctr, { case 0: { - make_srv_sess_info_0(&(ctr->sess.info0), resume_hnd, total_entries); + init_srv_sess_info_0(&(ctr->sess.info0), resume_hnd, total_entries); ctr->ptr_sess_ctr = 1; break; } case 1: { - make_srv_sess_info_1(&(ctr->sess.info1), resume_hnd, total_entries); + init_srv_sess_info_1(&(ctr->sess.info1), resume_hnd, total_entries); ctr->ptr_sess_ctr = 1; break; } default: { - DEBUG(5,("make_srv_sess_info_ctr: unsupported switch value %d\n", + DEBUG(5,("init_srv_sess_info_ctr: unsupported switch value %d\n", switch_value)); (*resume_hnd) = 0; (*total_entries) = 0; @@ -483,10 +458,10 @@ static uint32 make_srv_sess_info_ctr(SRV_SESS_INFO_CTR *ctr, /******************************************************************* makes a SRV_R_NET_SESS_ENUM structure. ********************************************************************/ -static void make_srv_r_net_sess_enum(SRV_R_NET_SESS_ENUM *r_n, +static void init_srv_r_net_sess_enum(SRV_R_NET_SESS_ENUM *r_n, uint32 resume_hnd, int sess_level, int switch_value) { - DEBUG(5,("make_srv_r_net_sess_enum: %d\n", __LINE__)); + DEBUG(5,("init_srv_r_net_sess_enum: %d\n", __LINE__)); r_n->sess_level = sess_level; if (sess_level == -1) @@ -495,13 +470,13 @@ static void make_srv_r_net_sess_enum(SRV_R_NET_SESS_ENUM *r_n, } else { - r_n->status = make_srv_sess_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries); + r_n->status = init_srv_sess_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries); } if (r_n->status != 0x0) { resume_hnd = 0; } - make_enum_hnd(&(r_n->enum_hnd), resume_hnd); + init_enum_hnd(&(r_n->enum_hnd), resume_hnd); } /******************************************************************* @@ -518,7 +493,7 @@ static void srv_reply_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, DEBUG(5,("srv_net_sess_enum: %d\n", __LINE__)); /* set up the */ - make_srv_r_net_sess_enum(&r_n, + init_srv_r_net_sess_enum(&r_n, get_enum_hnd(&q_n->enum_hnd), q_n->sess_level, q_n->ctr->switch_value); @@ -537,20 +512,10 @@ static void srv_reply_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, functions itself. yuck. ********************************************************************/ -static void make_srv_conn_info_0(SRV_CONN_INFO_0 *ss0, uint32 *snum, uint32 *stot) +static void init_srv_conn_info_0(SRV_CONN_INFO_0 *ss0, uint32 *snum, uint32 *stot) { - uint32 num_entries = 0; - struct connect_record *crec; - uint32 connection_count; - - if (!get_connection_status(&crec, &connection_count)) - { - (*snum) = 0; - (*stot) = 0; - return; - } - - (*stot) = connection_count; + uint32 num_entries = 0; + (*stot) = 1; if (ss0 == NULL) { @@ -558,13 +523,13 @@ static void make_srv_conn_info_0(SRV_CONN_INFO_0 *ss0, uint32 *snum, uint32 *sto return; } - DEBUG(0,("make_srv_conn_0_ss0\n")); + DEBUG(5,("init_srv_conn_0_ss0\n")); if (snum) { for (; (*snum) < (*stot) && num_entries < MAX_CONN_ENTRIES; (*snum)++) { - make_srv_conn_info0(&(ss0->info_0 [num_entries]), (*snum)); + init_srv_conn_info0(&(ss0->info_0 [num_entries]), (*stot)); /* move on to creating next connection */ /* move on to creating next conn */ @@ -590,8 +555,6 @@ static void make_srv_conn_info_0(SRV_CONN_INFO_0 *ss0, uint32 *snum, uint32 *sto (*stot) = 0; } - - free(crec); } /******************************************************************* @@ -602,13 +565,13 @@ static void make_srv_conn_info_0(SRV_CONN_INFO_0 *ss0, uint32 *snum, uint32 *sto functions itself. yuck. ********************************************************************/ -static void make_srv_conn_1_info(CONN_INFO_1 *se1, CONN_INFO_1_STR *str1, +static void init_srv_conn_1_info(CONN_INFO_1 *se1, CONN_INFO_1_STR *str1, uint32 id, uint32 type, uint32 num_opens, uint32 num_users, uint32 open_time, char *usr_name, char *net_name) { - make_srv_conn_info1 (se1 , id, type, num_opens, num_users, open_time, usr_name, net_name); - make_srv_conn_info1_str(str1, usr_name, net_name); + init_srv_conn_info1 (se1 , id, type, num_opens, num_users, open_time, usr_name, net_name); + init_srv_conn_info1_str(str1, usr_name, net_name); } /******************************************************************* @@ -619,23 +582,10 @@ static void make_srv_conn_1_info(CONN_INFO_1 *se1, CONN_INFO_1_STR *str1, functions itself. yuck. ********************************************************************/ -static void make_srv_conn_info_1(SRV_CONN_INFO_1 *ss1, uint32 *snum, uint32 *stot) +static void init_srv_conn_info_1(SRV_CONN_INFO_1 *ss1, uint32 *snum, uint32 *stot) { - uint32 num_entries = 0; - time_t current_time; - time_t diff; - - struct connect_record *crec; - uint32 connection_count; - - if (!get_connection_status(&crec, &connection_count)) - { - (*snum) = 0; - (*stot) = 0; - return; - } - - (*stot) = connection_count; + uint32 num_entries = 0; + (*stot) = 1; if (ss1 == NULL) { @@ -643,21 +593,15 @@ static void make_srv_conn_info_1(SRV_CONN_INFO_1 *ss1, uint32 *snum, uint32 *sto return; } - current_time=time(NULL); - - DEBUG(5,("make_srv_conn_1_ss1\n")); + DEBUG(5,("init_srv_conn_1_ss1\n")); if (snum) { for (; (*snum) < (*stot) && num_entries < MAX_CONN_ENTRIES; (*snum)++) { - diff = current_time - crec[num_entries].start; - make_srv_conn_1_info(&(ss1->info_1 [num_entries]), + init_srv_conn_1_info(&(ss1->info_1 [num_entries]), &(ss1->info_1_str[num_entries]), - (*snum), 0, 0, 1, diff,uidtoname(crec[num_entries].uid), - crec[num_entries].name); - -/* FIXME : type of connection + number of locked files */ + (*stot), 0x3, 1, 1, 3,"dummy_user", "IPC$"); /* move on to creating next connection */ /* move on to creating next conn */ @@ -682,18 +626,16 @@ static void make_srv_conn_info_1(SRV_CONN_INFO_1 *ss1, uint32 *snum, uint32 *sto (*stot) = 0; } - - free(crec); } /******************************************************************* makes a SRV_R_NET_CONN_ENUM structure. ********************************************************************/ -static uint32 make_srv_conn_info_ctr(SRV_CONN_INFO_CTR *ctr, +static uint32 init_srv_conn_info_ctr(SRV_CONN_INFO_CTR *ctr, int switch_value, uint32 *resume_hnd, uint32 *total_entries) { uint32 status = 0x0; - DEBUG(5,("make_srv_conn_info_ctr: %d\n", __LINE__)); + DEBUG(5,("init_srv_conn_info_ctr: %d\n", __LINE__)); ctr->switch_value = switch_value; @@ -701,19 +643,19 @@ static uint32 make_srv_conn_info_ctr(SRV_CONN_INFO_CTR *ctr, { case 0: { - make_srv_conn_info_0(&(ctr->conn.info0), resume_hnd, total_entries); + init_srv_conn_info_0(&(ctr->conn.info0), resume_hnd, total_entries); ctr->ptr_conn_ctr = 1; break; } case 1: { - make_srv_conn_info_1(&(ctr->conn.info1), resume_hnd, total_entries); + init_srv_conn_info_1(&(ctr->conn.info1), resume_hnd, total_entries); ctr->ptr_conn_ctr = 1; break; } default: { - DEBUG(5,("make_srv_conn_info_ctr: unsupported switch value %d\n", + DEBUG(5,("init_srv_conn_info_ctr: unsupported switch value %d\n", switch_value)); (*resume_hnd = 0); (*total_entries) = 0; @@ -729,10 +671,10 @@ static uint32 make_srv_conn_info_ctr(SRV_CONN_INFO_CTR *ctr, /******************************************************************* makes a SRV_R_NET_CONN_ENUM structure. ********************************************************************/ -static void make_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n, +static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n, uint32 resume_hnd, int conn_level, int switch_value) { - DEBUG(5,("make_srv_r_net_conn_enum: %d\n", __LINE__)); + DEBUG(5,("init_srv_r_net_conn_enum: %d\n", __LINE__)); r_n->conn_level = conn_level; if (conn_level == -1) @@ -741,13 +683,13 @@ static void make_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n, } else { - r_n->status = make_srv_conn_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries); + r_n->status = init_srv_conn_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries); } if (r_n->status != 0x0) { resume_hnd = 0; } - make_enum_hnd(&(r_n->enum_hnd), resume_hnd); + init_enum_hnd(&(r_n->enum_hnd), resume_hnd); } /******************************************************************* @@ -764,7 +706,7 @@ static void srv_reply_net_conn_enum(SRV_Q_NET_CONN_ENUM *q_n, DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__)); /* set up the */ - make_srv_r_net_conn_enum(&r_n, + init_srv_r_net_conn_enum(&r_n, get_enum_hnd(&q_n->enum_hnd), q_n->conn_level, q_n->ctr->switch_value); @@ -778,12 +720,12 @@ static void srv_reply_net_conn_enum(SRV_Q_NET_CONN_ENUM *q_n, /******************************************************************* fill in a file info level 3 structure. ********************************************************************/ -static void make_srv_file_3_info(FILE_INFO_3 *fl3, FILE_INFO_3_STR *str3, +static void init_srv_file_3_info(FILE_INFO_3 *fl3, FILE_INFO_3_STR *str3, uint32 fnum, uint32 perms, uint32 num_locks, char *path_name, char *user_name) { - make_srv_file_info3 (fl3 , fnum, perms, num_locks, path_name, user_name); - make_srv_file_info3_str(str3, path_name, user_name); + init_srv_file_info3 (fl3 , fnum, perms, num_locks, path_name, user_name); + init_srv_file_info3_str(str3, path_name, user_name); } /******************************************************************* @@ -794,7 +736,7 @@ static void make_srv_file_3_info(FILE_INFO_3 *fl3, FILE_INFO_3_STR *str3, functions itself. yuck. ********************************************************************/ -static void make_srv_file_info_3(SRV_FILE_INFO_3 *fl3, uint32 *fnum, uint32 *ftot) +static void init_srv_file_info_3(SRV_FILE_INFO_3 *fl3, uint32 *fnum, uint32 *ftot) { uint32 num_entries = 0; (*ftot) = 1; @@ -805,11 +747,11 @@ static void make_srv_file_info_3(SRV_FILE_INFO_3 *fl3, uint32 *fnum, uint32 *fto return; } - DEBUG(5,("make_srv_file_3_fl3\n")); + DEBUG(5,("init_srv_file_3_fl3\n")); for (; (*fnum) < (*ftot) && num_entries < MAX_FILE_ENTRIES; (*fnum)++) { - make_srv_file_3_info(&(fl3->info_3 [num_entries]), + init_srv_file_3_info(&(fl3->info_3 [num_entries]), &(fl3->info_3_str[num_entries]), (*fnum), 0x35, 0, "\\PIPE\\samr", "dummy user"); @@ -830,11 +772,11 @@ static void make_srv_file_info_3(SRV_FILE_INFO_3 *fl3, uint32 *fnum, uint32 *fto /******************************************************************* makes a SRV_R_NET_FILE_ENUM structure. ********************************************************************/ -static uint32 make_srv_file_info_ctr(SRV_FILE_INFO_CTR *ctr, +static uint32 init_srv_file_info_ctr(SRV_FILE_INFO_CTR *ctr, int switch_value, uint32 *resume_hnd, uint32 *total_entries) { uint32 status = 0x0; - DEBUG(5,("make_srv_file_info_ctr: %d\n", __LINE__)); + DEBUG(5,("init_srv_file_info_ctr: %d\n", __LINE__)); ctr->switch_value = switch_value; @@ -842,13 +784,13 @@ static uint32 make_srv_file_info_ctr(SRV_FILE_INFO_CTR *ctr, { case 3: { - make_srv_file_info_3(&(ctr->file.info3), resume_hnd, total_entries); + init_srv_file_info_3(&(ctr->file.info3), resume_hnd, total_entries); ctr->ptr_file_ctr = 1; break; } default: { - DEBUG(5,("make_srv_file_info_ctr: unsupported switch value %d\n", + DEBUG(5,("init_srv_file_info_ctr: unsupported switch value %d\n", switch_value)); (*resume_hnd = 0); (*total_entries) = 0; @@ -864,10 +806,10 @@ static uint32 make_srv_file_info_ctr(SRV_FILE_INFO_CTR *ctr, /******************************************************************* makes a SRV_R_NET_FILE_ENUM structure. ********************************************************************/ -static void make_srv_r_net_file_enum(SRV_R_NET_FILE_ENUM *r_n, +static void init_srv_r_net_file_enum(SRV_R_NET_FILE_ENUM *r_n, uint32 resume_hnd, int file_level, int switch_value) { - DEBUG(5,("make_srv_r_net_file_enum: %d\n", __LINE__)); + DEBUG(5,("init_srv_r_net_file_enum: %d\n", __LINE__)); r_n->file_level = file_level; if (file_level == 0) @@ -876,13 +818,13 @@ static void make_srv_r_net_file_enum(SRV_R_NET_FILE_ENUM *r_n, } else { - r_n->status = make_srv_file_info_ctr(r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries)); + r_n->status = init_srv_file_info_ctr(r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries)); } if (r_n->status != 0x0) { resume_hnd = 0; } - make_enum_hnd(&(r_n->enum_hnd), resume_hnd); + init_enum_hnd(&(r_n->enum_hnd), resume_hnd); } /******************************************************************* @@ -899,7 +841,7 @@ static void srv_reply_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, DEBUG(5,("srv_net_file_enum: %d\n", __LINE__)); /* set up the */ - make_srv_r_net_file_enum(&r_n, + init_srv_r_net_file_enum(&r_n, get_enum_hnd(&q_n->enum_hnd), q_n->file_level, q_n->ctr->switch_value); @@ -913,6 +855,7 @@ static void srv_reply_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, /******************************************************************* net server get info ********************************************************************/ + static void srv_reply_net_srv_get_info(SRV_Q_NET_SRV_GET_INFO *q_n, prs_struct *rdata) { @@ -927,12 +870,10 @@ static void srv_reply_net_srv_get_info(SRV_Q_NET_SRV_GET_INFO *q_n, { case 102: { - make_srv_info_102(&ctr.srv.sv102, - 500, /* platform id */ - global_myname, - lp_serverstring(), - lp_major_announce_version(), - lp_minor_announce_version(), + init_srv_info_102(&ctr.srv.sv102, + 500, global_myname, + string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH), + lp_major_announce_version(), lp_minor_announce_version(), lp_default_server_announce(), 0xffffffff, /* users */ 0xf, /* disc */ @@ -945,13 +886,11 @@ static void srv_reply_net_srv_get_info(SRV_Q_NET_SRV_GET_INFO *q_n, } case 101: { - make_srv_info_101(&ctr.srv.sv101, - 500, /* platform id */ - global_myname, - lp_major_announce_version(), - lp_minor_announce_version(), + init_srv_info_101(&ctr.srv.sv101, + 500, global_myname, + lp_major_announce_version(), lp_minor_announce_version(), lp_default_server_announce(), - lp_serverstring()); + string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); break; } default: @@ -962,7 +901,7 @@ static void srv_reply_net_srv_get_info(SRV_Q_NET_SRV_GET_INFO *q_n, } /* set up the net server get info structure */ - make_srv_r_net_srv_get_info(&r_n, q_n->switch_value, &ctr, status); + init_srv_r_net_srv_get_info(&r_n, q_n->switch_value, &ctr, status); /* store the response in the SMB stream */ srv_io_r_net_srv_get_info("", &r_n, rdata, 0); @@ -972,7 +911,7 @@ static void srv_reply_net_srv_get_info(SRV_Q_NET_SRV_GET_INFO *q_n, /******************************************************************* ********************************************************************/ -static void api_srv_net_srv_get_info( rpcsrv_struct *p, prs_struct *data, +static BOOL api_srv_net_srv_get_info( uint16 vuid, prs_struct *data, prs_struct *rdata ) { SRV_Q_NET_SRV_GET_INFO q_n; @@ -982,12 +921,14 @@ static void api_srv_net_srv_get_info( rpcsrv_struct *p, prs_struct *data, /* construct reply. always indicate success */ srv_reply_net_srv_get_info(&q_n, rdata); + + return True; } /******************************************************************* ********************************************************************/ -static void api_srv_net_file_enum( rpcsrv_struct *p, prs_struct *data, +static BOOL api_srv_net_file_enum( uint16 vuid, prs_struct *data, prs_struct *rdata ) { SRV_Q_NET_FILE_ENUM q_n; @@ -1000,12 +941,14 @@ static void api_srv_net_file_enum( rpcsrv_struct *p, prs_struct *data, /* construct reply. always indicate success */ srv_reply_net_file_enum(&q_n, rdata); + + return True; } /******************************************************************* ********************************************************************/ -static void api_srv_net_conn_enum( rpcsrv_struct *p, prs_struct *data, +static BOOL api_srv_net_conn_enum( uint16 vuid, prs_struct *data, prs_struct *rdata ) { SRV_Q_NET_CONN_ENUM q_n; @@ -1018,12 +961,14 @@ static void api_srv_net_conn_enum( rpcsrv_struct *p, prs_struct *data, /* construct reply. always indicate success */ srv_reply_net_conn_enum(&q_n, rdata); + + return True; } /******************************************************************* ********************************************************************/ -static void api_srv_net_sess_enum( rpcsrv_struct *p, prs_struct *data, +static BOOL api_srv_net_sess_enum( uint16 vuid, prs_struct *data, prs_struct *rdata ) { SRV_Q_NET_SESS_ENUM q_n; @@ -1036,30 +981,63 @@ static void api_srv_net_sess_enum( rpcsrv_struct *p, prs_struct *data, /* construct reply. always indicate success */ srv_reply_net_sess_enum(&q_n, rdata); + + return True; } /******************************************************************* + RPC to enumerate shares. ********************************************************************/ -static void api_srv_net_share_enum( rpcsrv_struct *p, prs_struct *data, + +static BOOL api_srv_net_share_enum( uint16 vuid, prs_struct *data, prs_struct *rdata ) { SRV_Q_NET_SHARE_ENUM q_n; - SRV_SHARE_INFO_CTR ctr; + BOOL ret; - q_n.ctr = &ctr; + /* Unmarshall the net server get enum. */ + if(!srv_io_q_net_share_enum("", &q_n, data, 0)) { + DEBUG(0,("api_srv_net_share_enum: Failed to unmarshall SRV_Q_NET_SHARE_ENUM.\n")); + return False; + } - /* grab the net server get enum */ - srv_io_q_net_share_enum("", &q_n, data, 0); + ret = srv_reply_net_share_enum(&q_n, rdata); - /* construct reply. always indicate success */ - srv_reply_net_share_enum(&q_n, rdata); + /* Free any data allocated in the unmarshalling. */ + free_srv_q_net_share_enum(&q_n); + + return ret; +} + +/******************************************************************* + RPC to return share information. +********************************************************************/ + +static BOOL api_srv_net_share_get_info( uint16 vuid, prs_struct *data, + prs_struct *rdata ) +{ + SRV_Q_NET_SHARE_GET_INFO q_n; + BOOL ret; + + /* Unmarshall the net server get info. */ + if(!srv_io_q_net_share_get_info("", &q_n, data, 0)) { + DEBUG(0,("api_srv_net_share_get_info: Failed to unmarshall SRV_Q_NET_SHARE_GET_INFO.\n")); + return False; + } + + ret = srv_reply_net_share_get_info(&q_n, rdata); + + /* Free any data allocated in the unmarshalling. */ + free_srv_q_net_share_get_info(&q_n); + + return ret; } /******************************************************************* time of day ********************************************************************/ -static void srv_reply_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_n, +static BOOL srv_reply_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_n, prs_struct *rdata) { SRV_R_NET_REMOTE_TOD r_n; @@ -1076,7 +1054,7 @@ static void srv_reply_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_n, t = gmtime(&unixdate); /* set up the */ - make_time_of_day_info(&tod, + init_time_of_day_info(&tod, unixdate, 0, t->tm_hour, @@ -1094,10 +1072,12 @@ static void srv_reply_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_n, srv_io_r_net_remote_tod("", &r_n, rdata, 0); DEBUG(5,("srv_reply_net_remote_tod: %d\n", __LINE__)); + + return True; } /******************************************************************* ********************************************************************/ -static void api_srv_net_remote_tod( rpcsrv_struct *p, prs_struct *data, +static BOOL api_srv_net_remote_tod( uint16 vuid, prs_struct *data, prs_struct *rdata ) { SRV_Q_NET_REMOTE_TOD q_n; @@ -1107,6 +1087,8 @@ static void api_srv_net_remote_tod( rpcsrv_struct *p, prs_struct *data, /* construct reply. always indicate success */ srv_reply_net_remote_tod(&q_n, rdata); + + return True; } @@ -1115,20 +1097,20 @@ static void api_srv_net_remote_tod( rpcsrv_struct *p, prs_struct *data, ********************************************************************/ struct api_struct api_srv_cmds[] = { - { "SRV_NETCONNENUM" , SRV_NETCONNENUM , api_srv_net_conn_enum }, - { "SRV_NETSESSENUM" , SRV_NETSESSENUM , api_srv_net_sess_enum }, - { "SRV_NETSHAREENUM" , SRV_NETSHAREENUM , api_srv_net_share_enum }, - { "SRV_NETFILEENUM" , SRV_NETFILEENUM , api_srv_net_file_enum }, - { "SRV_NET_SRV_GET_INFO", SRV_NET_SRV_GET_INFO, api_srv_net_srv_get_info }, - { "SRV_NET_REMOTE_TOD" , SRV_NET_REMOTE_TOD , api_srv_net_remote_tod }, - { NULL , 0 , NULL } + { "SRV_NETCONNENUM" , SRV_NETCONNENUM , api_srv_net_conn_enum }, + { "SRV_NETSESSENUM" , SRV_NETSESSENUM , api_srv_net_sess_enum }, + { "SRV_NETSHAREENUM" , SRV_NETSHAREENUM , api_srv_net_share_enum }, + { "SRV_NET_SHARE_GET_INFO", SRV_NET_SHARE_GET_INFO, api_srv_net_share_get_info }, + { "SRV_NETFILEENUM" , SRV_NETFILEENUM , api_srv_net_file_enum }, + { "SRV_NET_SRV_GET_INFO" , SRV_NET_SRV_GET_INFO , api_srv_net_srv_get_info }, + { "SRV_NET_REMOTE_TOD" , SRV_NET_REMOTE_TOD , api_srv_net_remote_tod }, + { NULL , 0 , NULL } }; /******************************************************************* receives a srvsvc pipe and responds. ********************************************************************/ -BOOL api_srvsvc_rpc(rpcsrv_struct *p, prs_struct *data) +BOOL api_srvsvc_rpc(pipes_struct *p, prs_struct *data) { return api_rpcTNP(p, "api_srvsvc_rpc", api_srv_cmds, data); } - diff --git a/source3/rpc_server/srv_util.c b/source3/rpc_server/srv_util.c index 25dceb41a0..097ab92d76 100644 --- a/source3/rpc_server/srv_util.c +++ b/source3/rpc_server/srv_util.c @@ -22,4 +22,325 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* retired module */ +/* this module apparently provides an implementation of DCE/RPC over a + * named pipe (IPC$ connection using SMBtrans). details of DCE/RPC + * documentation are available (in on-line form) from the X-Open group. + * + * this module should provide a level of abstraction between SMB + * and DCE/RPC, while minimising the amount of mallocs, unnecessary + * data copies, and network traffic. + * + * in this version, which takes a "let's learn what's going on and + * get something running" approach, there is additional network + * traffic generated, but the code should be easier to understand... + * + * ... if you read the docs. or stare at packets for weeks on end. + * + */ + +#include "includes.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + +/* + * A list of the rids of well known BUILTIN and Domain users + * and groups. + */ + +rid_name builtin_alias_rids[] = +{ + { BUILTIN_ALIAS_RID_ADMINS , "Administrators" }, + { BUILTIN_ALIAS_RID_USERS , "Users" }, + { BUILTIN_ALIAS_RID_GUESTS , "Guests" }, + { BUILTIN_ALIAS_RID_POWER_USERS , "Power Users" }, + + { BUILTIN_ALIAS_RID_ACCOUNT_OPS , "Account Operators" }, + { BUILTIN_ALIAS_RID_SYSTEM_OPS , "System Operators" }, + { BUILTIN_ALIAS_RID_PRINT_OPS , "Print Operators" }, + { BUILTIN_ALIAS_RID_BACKUP_OPS , "Backup Operators" }, + { BUILTIN_ALIAS_RID_REPLICATOR , "Replicator" }, + { 0 , NULL } +}; + +/* array lookup of well-known Domain RID users. */ +rid_name domain_user_rids[] = +{ + { DOMAIN_USER_RID_ADMIN , "Administrator" }, + { DOMAIN_USER_RID_GUEST , "Guest" }, + { 0 , NULL } +}; + +/* array lookup of well-known Domain RID groups. */ +rid_name domain_group_rids[] = +{ + { DOMAIN_GROUP_RID_ADMINS , "Domain Admins" }, + { DOMAIN_GROUP_RID_USERS , "Domain Users" }, + { DOMAIN_GROUP_RID_GUESTS , "Domain Guests" }, + { 0 , NULL } +}; + +int make_dom_gids(char *gids_str, DOM_GID **ppgids) +{ + char *ptr; + pstring s2; + int count; + DOM_GID *gids; + + *ppgids = NULL; + + DEBUG(4,("make_dom_gids: %s\n", gids_str)); + + if (gids_str == NULL || *gids_str == 0) + return 0; + + for (count = 0, ptr = gids_str; + next_token(&ptr, s2, NULL, sizeof(s2)); + count++) + ; + + gids = (DOM_GID *)malloc( sizeof(DOM_GID) * count ); + if(!gids) + { + DEBUG(0,("make_dom_gids: malloc fail !\n")); + return 0; + } + + for (count = 0, ptr = gids_str; + next_token(&ptr, s2, NULL, sizeof(s2)) && + count < LSA_MAX_GROUPS; + count++) + { + /* the entries are of the form GID/ATTR, ATTR being optional.*/ + char *attr; + uint32 rid = 0; + int i; + + attr = strchr(s2,'/'); + if (attr) + *attr++ = 0; + + if (!attr || !*attr) + attr = "7"; /* default value for attribute is 7 */ + + /* look up the RID string and see if we can turn it into a rid number */ + for (i = 0; builtin_alias_rids[i].name != NULL; i++) + { + if (strequal(builtin_alias_rids[i].name, s2)) + { + rid = builtin_alias_rids[i].rid; + break; + } + } + + if (rid == 0) + rid = atoi(s2); + + if (rid == 0) + { + DEBUG(1,("make_dom_gids: unknown well-known alias RID %s/%s\n", s2, attr)); + count--; + } + else + { + gids[count].g_rid = rid; + gids[count].attr = atoi(attr); + + DEBUG(5,("group id: %d attr: %d\n", gids[count].g_rid, gids[count].attr)); + } + } + + *ppgids = gids; + return count; +} + + +/******************************************************************* + gets a domain user's groups + ********************************************************************/ +void get_domain_user_groups(char *domain_groups, char *user) +{ + pstring tmp; + + if (domain_groups == NULL || user == NULL) return; + + /* any additional groups this user is in. e.g power users */ + pstrcpy(domain_groups, lp_domain_groups()); + + /* can only be a user or a guest. cannot be guest _and_ admin */ + if (user_in_list(user, lp_domain_guest_group())) + { + slprintf(tmp, sizeof(tmp) - 1, " %ld/7 ", DOMAIN_GROUP_RID_GUESTS); + pstrcat(domain_groups, tmp); + + DEBUG(3,("domain guest group access %s granted\n", tmp)); + } + else + { + slprintf(tmp, sizeof(tmp) -1, " %ld/7 ", DOMAIN_GROUP_RID_USERS); + pstrcat(domain_groups, tmp); + + DEBUG(3,("domain group access %s granted\n", tmp)); + + if (user_in_list(user, lp_domain_admin_group())) + { + slprintf(tmp, sizeof(tmp) - 1, " %ld/7 ", DOMAIN_GROUP_RID_ADMINS); + pstrcat(domain_groups, tmp); + + DEBUG(3,("domain admin group access %s granted\n", tmp)); + } + } +} + + +/******************************************************************* + lookup_group_name + ********************************************************************/ +uint32 lookup_group_name(uint32 rid, char *group_name, uint32 *type) +{ + int i = 0; + (*type) = SID_NAME_DOM_GRP; + + DEBUG(5,("lookup_group_name: rid: %d", rid)); + + while (domain_group_rids[i].rid != rid && domain_group_rids[i].rid != 0) + { + i++; + } + + if (domain_group_rids[i].rid != 0) + { + fstrcpy(group_name, domain_group_rids[i].name); + DEBUG(5,(" = %s\n", group_name)); + return 0x0; + } + + DEBUG(5,(" none mapped\n")); + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_alias_name + ********************************************************************/ +uint32 lookup_alias_name(uint32 rid, char *alias_name, uint32 *type) +{ + int i = 0; + (*type) = SID_NAME_WKN_GRP; + + DEBUG(5,("lookup_alias_name: rid: %d", rid)); + + while (builtin_alias_rids[i].rid != rid && builtin_alias_rids[i].rid != 0) + { + i++; + } + + if (builtin_alias_rids[i].rid != 0) + { + fstrcpy(alias_name, builtin_alias_rids[i].name); + DEBUG(5,(" = %s\n", alias_name)); + return 0x0; + } + + DEBUG(5,(" none mapped\n")); + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_user_name + ********************************************************************/ +uint32 lookup_user_name(uint32 rid, char *user_name, uint32 *type) +{ + struct sam_disp_info *disp_info; + int i = 0; + (*type) = SID_NAME_USER; + + DEBUG(5,("lookup_user_name: rid: %d", rid)); + + /* look up the well-known domain user rids first */ + while (domain_user_rids[i].rid != rid && domain_user_rids[i].rid != 0) + { + i++; + } + + if (domain_user_rids[i].rid != 0) + { + fstrcpy(user_name, domain_user_rids[i].name); + DEBUG(5,(" = %s\n", user_name)); + return 0x0; + } + + /* ok, it's a user. find the user account */ + become_root(True); + disp_info = getsamdisprid(rid); + unbecome_root(True); + + if (disp_info != NULL) + { + fstrcpy(user_name, disp_info->smb_name); + DEBUG(5,(" = %s\n", user_name)); + return 0x0; + } + + DEBUG(5,(" none mapped\n")); + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_group_rid + ********************************************************************/ +uint32 lookup_group_rid(char *group_name, uint32 *rid) +{ + char *grp_name; + int i = -1; /* start do loop at -1 */ + + do /* find, if it exists, a group rid for the group name*/ + { + i++; + (*rid) = domain_group_rids[i].rid; + grp_name = domain_group_rids[i].name; + + } while (grp_name != NULL && !strequal(grp_name, group_name)); + + return (grp_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_alias_rid + ********************************************************************/ +uint32 lookup_alias_rid(char *alias_name, uint32 *rid) +{ + char *als_name; + int i = -1; /* start do loop at -1 */ + + do /* find, if it exists, a alias rid for the alias name*/ + { + i++; + (*rid) = builtin_alias_rids[i].rid; + als_name = builtin_alias_rids[i].name; + + } while (als_name != NULL && !strequal(als_name, alias_name)); + + return (als_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_user_rid + ********************************************************************/ +uint32 lookup_user_rid(char *user_name, uint32 *rid) +{ + struct sam_passwd *sam_pass; + (*rid) = 0; + + /* find the user account */ + become_root(True); + sam_pass = getsam21pwnam(user_name); + unbecome_root(True); + + if (sam_pass != NULL) + { + (*rid) = sam_pass->user_rid; + return 0x0; + } + + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} diff --git a/source3/rpc_server/srv_wkssvc.c b/source3/rpc_server/srv_wkssvc.c index e97ae1ee6e..658cadc625 100644 --- a/source3/rpc_server/srv_wkssvc.c +++ b/source3/rpc_server/srv_wkssvc.c @@ -46,7 +46,7 @@ static void create_wks_info_100(WKS_INFO_100 *inf) pstrcpy (domain , lp_workgroup()); strupper(domain); - make_wks_info_100(inf, + init_wks_info_100(inf, 0x000001f4, /* platform id info */ lp_major_announce_version(), lp_minor_announce_version(), @@ -69,7 +69,7 @@ static void wks_reply_query_info(WKS_Q_QUERY_INFO *q_u, DEBUG(5,("wks_query_info: %d\n", __LINE__)); create_wks_info_100(&wks100); - make_wks_r_query_info(&r_u, q_u->switch_value, &wks100, status); + init_wks_r_query_info(&r_u, q_u->switch_value, &wks100, status); /* store the response in the SMB stream */ wks_io_r_query_info("", &r_u, rdata, 0); @@ -80,7 +80,7 @@ static void wks_reply_query_info(WKS_Q_QUERY_INFO *q_u, /******************************************************************* api_wks_query_info ********************************************************************/ -static void api_wks_query_info( rpcsrv_struct *p, prs_struct *data, +static BOOL api_wks_query_info( uint16 vuid, prs_struct *data, prs_struct *rdata ) { WKS_Q_QUERY_INFO q_u; @@ -90,6 +90,8 @@ static void api_wks_query_info( rpcsrv_struct *p, prs_struct *data, /* construct reply. always indicate success */ wks_reply_query_info(&q_u, rdata, 0x0); + + return True; } @@ -105,7 +107,7 @@ struct api_struct api_wks_cmds[] = /******************************************************************* receives a wkssvc pipe and responds. ********************************************************************/ -BOOL api_wkssvc_rpc(rpcsrv_struct *p, prs_struct *data) +BOOL api_wkssvc_rpc(pipes_struct *p, prs_struct *data) { return api_rpcTNP(p, "api_wkssvc_rpc", api_wks_cmds, data); } -- cgit