diff options
-rw-r--r-- | docs/docbook/manpages/smb.conf.5.sgml | 22 | ||||
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/include/smb.h | 9 | ||||
-rw-r--r-- | source3/lib/substitute.c | 52 | ||||
-rw-r--r-- | source3/lib/util_getent.c | 30 | ||||
-rw-r--r-- | source3/param/loadparm.c | 22 | ||||
-rw-r--r-- | source3/passdb/passdb.c | 310 | ||||
-rw-r--r-- | source3/passdb/pdb_get_set.c | 76 | ||||
-rw-r--r-- | source3/passdb/pdb_interface.c | 16 | ||||
-rw-r--r-- | source3/passdb/pdb_ldap.c | 50 | ||||
-rw-r--r-- | source3/passdb/pdb_smbpasswd.c | 55 | ||||
-rw-r--r-- | source3/passdb/pdb_tdb.c | 99 | ||||
-rw-r--r-- | source3/passdb/pdb_unix.c | 126 | ||||
-rw-r--r-- | source3/rpc_parse/parse_samr.c | 23 | ||||
-rw-r--r-- | source3/rpc_server/srv_lsa_nt.c | 4 | ||||
-rw-r--r-- | source3/script/mkproto.awk | 10 | ||||
-rw-r--r-- | source3/smbd/lanman.c | 29 | ||||
-rw-r--r-- | source3/smbd/password.c | 14 | ||||
-rw-r--r-- | source3/smbd/service.c | 19 | ||||
-rw-r--r-- | source3/utils/net_rpc_join.c | 10 |
20 files changed, 642 insertions, 336 deletions
diff --git a/docs/docbook/manpages/smb.conf.5.sgml b/docs/docbook/manpages/smb.conf.5.sgml index f15cb8c406..4911d3a914 100644 --- a/docs/docbook/manpages/smb.conf.5.sgml +++ b/docs/docbook/manpages/smb.conf.5.sgml @@ -5172,13 +5172,26 @@ <para>Any characters after the (optional) second : are passed to the plugin for its own processing</para> </listitem> - + + <listitem><para><command>unixsam</command> - Allows samba to map all (other) available unix users</para> + + <para>This backend uses the standard unix database for retrieving users. Users included + in this pdb are NOT listed in samba user listings and users included in this pdb won't be + able to login. The use of this backend is to always be able to display the owner of a file + on the samba server - even when the user doesn't have a 'real' samba account in one of the + other passdb backends. + </para> + + <para>This backend should always be the last backend listed, since it contains all users in + the unix passdb and might 'override' mappings if specified earlier. It's meant to only return + accounts for users that aren't covered by the previous backends.</para> + </listitem> </itemizedlist> </para> - <para>Default: <command>passdb backend = smbpasswd</command></para> - <para>Example: <command>passdb backend = tdbsam:/etc/samba/private/passdb.tdb smbpasswd:/etc/samba/smbpasswd</command></para> - <para>Example: <command>passdb backend = ldapsam_nua:ldaps://ldap.example.com</command></para> + <para>Default: <command>passdb backend = smbpasswd unixsam</command></para> + <para>Example: <command>passdb backend = tdbsam:/etc/samba/private/passdb.tdb smbpasswd:/etc/samba/smbpasswd unixsam</command></para> + <para>Example: <command>passdb backend = ldapsam_nua:ldaps://ldap.example.com unixsam</command></para> <para>Example: <command>passdb backend = plugin:/usr/local/samba/lib/my_passdb.so:my_plugin_args tdbsam:/etc/samba/private/passdb.tdb</command></para> </listitem> </varlistentry> @@ -6979,7 +6992,6 @@ </varlistentry> - <varlistentry> <term><anchor id="STATCACHE">stat cache (G)</term> <listitem><para>This parameter determines if <ulink diff --git a/source3/Makefile.in b/source3/Makefile.in index c78dc28d0b..3a97f78cab 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -196,7 +196,7 @@ LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o PASSDB_OBJ = passdb/passdb.o passdb/pdb_interface.o passdb/pdb_get_set.o \ passdb/machine_sid.o passdb/pdb_smbpasswd.o \ passdb/pdb_tdb.o passdb/pdb_ldap.o passdb/pdb_plugin.o \ - passdb/pdb_nisplus.o + passdb/pdb_nisplus.o passdb/pdb_unix.o GROUPDB_OBJ = groupdb/mapping.o diff --git a/source3/include/smb.h b/source3/include/smb.h index 0e5a85ad15..ca146ff50a 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -581,7 +581,7 @@ typedef struct { #define FLAG_SAM_KICKOFFTIME 0x00000100 #define FLAG_SAM_CANCHANGETIME 0x00000200 #define FLAG_SAM_MUSTCHANGETIME 0x00000400 - +#define FLAG_SAM_PLAINTEXT_PW 0x00000800 #define IS_SAM_UNIX_USER(x) \ ((pdb_get_init_flag(x) & FLAG_SAM_UID) \ @@ -595,7 +595,7 @@ typedef struct sam_passwd void (*free_fn)(struct sam_passwd **); - struct pdb_methods *methods; + struct pdb_methods *methods; struct user_data { /* initiailization flags */ @@ -612,6 +612,7 @@ typedef struct sam_passwd char * domain; /* Windows Domain name */ char * nt_username; /* Windows username string */ char * full_name; /* user's full name string */ + char * unix_home_dir; /* UNIX home directory string */ char * home_dir; /* home directory string */ char * dir_drive; /* home directory drive string */ char * logon_script; /* logon script string */ @@ -628,6 +629,7 @@ typedef struct sam_passwd DATA_BLOB lm_pw; /* .data is Null if no password */ DATA_BLOB nt_pw; /* .data is Null if no password */ + DATA_BLOB plaintext_pw; /* .data is Null if not available */ uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */ uint32 unknown_3; /* 0x00ff ffff */ @@ -639,6 +641,7 @@ typedef struct sam_passwd uint32 unknown_5; /* 0x0002 0000 */ uint32 unknown_6; /* 0x0000 04ec */ } private; + /* Lets see if the remaining code can get the hint that you are meant to use the pdb_...() functions. */ @@ -1578,6 +1581,8 @@ typedef struct user_struct userdom_struct user; char *homedir; + char *unix_homedir; + char *logon_script; BOOL guest; diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index e878ee8cbf..09921c145d 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -279,6 +279,58 @@ void standard_sub_advanced(int snum, const char *user, const char *connectpath, standard_sub_basic(smb_name, str); } +const char *standard_sub_specified(TALLOC_CTX *mem_ctx, const char *input_string, + const char *username, + const char *domain, + uid_t uid, + gid_t gid) +{ + pstring input_pstring; + char *p, *s; + + pstrcpy(input_pstring, input_string); + + for (s=input_pstring; (p=strchr_m(s, '%')); s=p) { + + int l = sizeof(pstring) - (int)(p-input_pstring); + + switch (*(p+1)) { + case 'U' : + string_sub(p,"%U",username,l); + break; + case 'u' : + string_sub(p,"%u",username,l); + break; + case 'G' : + case 'g' : + if (gid != -1) { + string_sub(p,"%G",gidtoname(gid),l); + string_sub(p,"%g",gidtoname(gid),l); + } else { + string_sub(p,"%G","NO_GROUP",l); + string_sub(p,"%g","NO_GROUP",l); + } + break; + case 'D' : + string_sub(p,"%D", domain,l); + break; + case 'N' : + string_sub(p,"%N", automount_server(username),l); + break; + case '\0': + p++; + break; /* don't run off the end of the string */ + + default: p+=2; + break; + } + } + + standard_sub_basic(username, input_pstring); + + return talloc_strdup(mem_ctx, input_pstring); +} + /**************************************************************************** Do some standard substitutions in a string. ****************************************************************************/ diff --git a/source3/lib/util_getent.c b/source3/lib/util_getent.c index 02e4b932de..2e76121aae 100644 --- a/source3/lib/util_getent.c +++ b/source3/lib/util_getent.c @@ -277,20 +277,24 @@ struct sys_userlist *get_users_in_group(const char *gname) DOM_SID sid; enum SID_NAME_USE name_type; - (void) split_domain_and_name(gname, domain, groupname); - - /* - * If we're doing this via winbindd, don't do the - * entire group list enumeration as we know this is - * pointless (and slow). - */ - - if (winbind_lookup_name(domain, groupname, &sid, &name_type) && name_type == SID_NAME_DOM_GRP) { - if ((gptr = (struct group *)getgrnam(gname)) == NULL) - return NULL; - return add_members_to_userlist(list_head, gptr); + /* No point using winbind if we can't split it in the + first place */ + if (split_domain_and_name(gname, domain, groupname)) { + + /* + * If we're doing this via winbindd, don't do the + * entire group list enumeration as we know this is + * pointless (and slow). + */ + + if (winbind_lookup_name(domain, groupname, &sid, &name_type) + && name_type == SID_NAME_DOM_GRP) { + if ((gptr = (struct group *)getgrnam(gname)) == NULL) + return NULL; + return add_members_to_userlist(list_head, gptr); + } } - + setgrent(); while((gptr = getgrent()) != NULL) { if (strequal(gname, gptr->gr_name)) { diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 788b25a53d..79eef6ed5e 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -138,7 +138,7 @@ typedef struct char *szAddGroupScript; char *szDelGroupScript; char *szAddUserToGroupScript; - char *szDelUserToGroupScript; + char *szDelUserFromGroupScript; char *szAddMachineScript; char *szShutdownScript; char *szAbortShutdownScript; @@ -893,7 +893,7 @@ static struct parm_struct parm_table[] = { {"add group script", P_STRING, P_GLOBAL, &Globals.szAddGroupScript, NULL, NULL, 0}, {"delete group script", P_STRING, P_GLOBAL, &Globals.szDelGroupScript, NULL, NULL, 0}, {"add user to group script", P_STRING, P_GLOBAL, &Globals.szAddUserToGroupScript, NULL, NULL, 0}, - {"delete user from group script", P_STRING, P_GLOBAL, &Globals.szDelUserToGroupScript, NULL, NULL, 0}, + {"delete user from group script", P_STRING, P_GLOBAL, &Globals.szDelUserFromGroupScript, NULL, NULL, 0}, {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, 0}, {"shutdown script", P_STRING, P_GLOBAL, &Globals.szShutdownScript, NULL, NULL, 0}, {"abort shutdown script", P_STRING, P_GLOBAL, &Globals.szAbortShutdownScript, NULL, NULL, 0}, @@ -1187,7 +1187,7 @@ static void init_globals(void) string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE); string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR); - string_set(&Globals.szPassdbBackend, "smbpasswd"); + string_set(&Globals.szPassdbBackend, "smbpasswd unixsam"); /* use the new 'hash2' method by default */ string_set(&Globals.szManglingMethod, "hash2"); @@ -1416,6 +1416,8 @@ static char *lp_string(const char *s) #define FN_GLOBAL_STRING(fn_name,ptr) \ char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));} +#define FN_GLOBAL_CONST_STRING(fn_name,ptr) \ + const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");} #define FN_GLOBAL_LIST(fn_name,ptr) \ char **fn_name(void) {return(*(char ***)(ptr));} #define FN_GLOBAL_BOOL(fn_name,ptr) \ @@ -1475,10 +1477,10 @@ FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkGroup) FN_GLOBAL_STRING(lp_realm, &Globals.szRealm) FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver) FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap) -FN_GLOBAL_STRING(lp_logon_script, &Globals.szLogonScript) -FN_GLOBAL_STRING(lp_logon_path, &Globals.szLogonPath) -FN_GLOBAL_STRING(lp_logon_drive, &Globals.szLogonDrive) -FN_GLOBAL_STRING(lp_logon_home, &Globals.szLogonHome) +FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript) +FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath) +FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive) +FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome) FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce) FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync) FN_GLOBAL_STRING(lp_wins_server_list, &Globals.szWINSserver) @@ -1495,7 +1497,7 @@ FN_GLOBAL_STRING(lp_guestaccount, &Globals.szGuestaccount) FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript) FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript) FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript) -FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserToGroupScript) +FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript) FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript) @@ -3873,7 +3875,7 @@ char *lp_printername(int snum) #define P_LIST_ABS 16 /* P_LIST Allocation Block Size */ -char **lp_list_make(char *string) +char **lp_list_make(const char *string) { char **list, **rlist; char *str, *s; @@ -3891,7 +3893,7 @@ char **lp_list_make(char *string) list = NULL; str = s; - while (next_token(&str, tok, LIST_SEP, sizeof(pstring))) + while (next_token(&str, tok, LIST_SEP, sizeof(tok))) { if (num == lsize) { lsize += P_LIST_ABS; diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index d34866fa63..edae00389e 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -30,6 +30,7 @@ */ extern DOM_SID global_sam_sid; +extern pstring global_myname; /************************************************************ Fill the SAM_ACCOUNT with default values. @@ -150,32 +151,39 @@ NTSTATUS pdb_init_sam(SAM_ACCOUNT **user) Initialises a struct sam_passwd with sane values. ************************************************************/ -NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd) +NTSTATUS pdb_fill_sam_pw(SAM_ACCOUNT *sam_account, const struct passwd *pwd) { - pstring str; GROUP_MAP map; uint32 rid; - NTSTATUS nt_status; if (!pwd) { - new_sam_acct = NULL; return NT_STATUS_UNSUCCESSFUL; } - if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(new_sam_acct))) { - new_sam_acct = NULL; - return nt_status; - } + pdb_fill_default_sam(sam_account); - pdb_set_username(*new_sam_acct, pwd->pw_name); - pdb_set_fullname(*new_sam_acct, pwd->pw_gecos); + pdb_set_username(sam_account, pwd->pw_name); + pdb_set_fullname(sam_account, pwd->pw_gecos); - pdb_set_uid(*new_sam_acct, pwd->pw_uid); - pdb_set_gid(*new_sam_acct, pwd->pw_gid); + pdb_set_unix_homedir(sam_account, pwd->pw_dir); + + pdb_set_domain (sam_account, lp_workgroup()); + + pdb_set_uid(sam_account, pwd->pw_uid); + pdb_set_gid(sam_account, pwd->pw_gid); - /* let the backends set the rid!! - pdb_set_user_rid(*new_sam_acct, pdb_uid_to_user_rid(pwd->pw_uid)); - -- simo */ + /* When we get a proper uid -> SID and SID -> uid allocation + mechinism, we should call it here. + + We can't just set this to 0 or allow it only to be filled + in when added to the backend, becouse the user's SID + may already be in security descriptors etc. + + -- abartlet 11-May-02 + */ + + pdb_set_user_rid(sam_account, + fallback_pdb_uid_to_user_rid(pwd->pw_uid)); /* call the mapping code here */ if(get_group_map_from_gid(pwd->pw_gid, &map, MAPPING_WITHOUT_PRIV)) { @@ -185,24 +193,67 @@ NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd) rid=pdb_gid_to_group_rid(pwd->pw_gid); } - pdb_set_group_rid(*new_sam_acct, rid); + pdb_set_group_rid(sam_account, rid); + + /* check if this is a user account or a machine account */ + if (pwd->pw_name[strlen(pwd->pw_name)-1] != '$') + { + pdb_set_profile_path(sam_account, + standard_sub_specified((sam_account)->mem_ctx, + lp_logon_path(), + pwd->pw_name, global_myname, + pwd->pw_uid, pwd->pw_gid), + False); + + pdb_set_homedir(sam_account, + standard_sub_specified((sam_account)->mem_ctx, + lp_logon_home(), + pwd->pw_name, global_myname, + pwd->pw_uid, pwd->pw_gid), + False); + + pdb_set_dir_drive(sam_account, + standard_sub_specified((sam_account)->mem_ctx, + lp_logon_drive(), + pwd->pw_name, global_myname, + pwd->pw_uid, pwd->pw_gid), + False); + + pdb_set_logon_script(sam_account, + standard_sub_specified((sam_account)->mem_ctx, + lp_logon_script(), + pwd->pw_name, global_myname, + pwd->pw_uid, pwd->pw_gid), + False); + } + return NT_STATUS_OK; +} - pstrcpy(str, lp_logon_path()); - standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str); - pdb_set_profile_path(*new_sam_acct, str, False); - - pstrcpy(str, lp_logon_home()); - standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str); - pdb_set_homedir(*new_sam_acct, str, False); - - pstrcpy(str, lp_logon_drive()); - standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str); - pdb_set_dir_drive(*new_sam_acct, str, False); - pstrcpy(str, lp_logon_script()); - standard_sub_advanced(-1, pwd->pw_name, "", pwd->pw_gid, pwd->pw_name, str); - pdb_set_logon_script(*new_sam_acct, str, False); - +/************************************************************* + Initialises a struct sam_passwd with sane values. + ************************************************************/ + +NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd) +{ + NTSTATUS nt_status; + + if (!pwd) { + new_sam_acct = NULL; + return NT_STATUS_UNSUCCESSFUL; + } + + if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(new_sam_acct))) { + new_sam_acct = NULL; + return nt_status; + } + + if (!NT_STATUS_IS_OK(nt_status = pdb_fill_sam_pw(*new_sam_acct, pwd))) { + pdb_free_sam(new_sam_acct); + new_sam_acct = NULL; + return nt_status; + } + return NT_STATUS_OK; } @@ -210,18 +261,21 @@ NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd) /** * Free the contets of the SAM_ACCOUNT, but not the structure. * - * Also wipes the LM and NT hashes from memory. + * Also wipes the LM and NT hashes and plaintext passwrod from + * memory. * * @param user SAM_ACCOUNT to free members of. **/ static void pdb_free_sam_contents(SAM_ACCOUNT *user) { - /* As we start mallocing more strings this is where - we should free them. */ + + /* Kill off sensitive data. Free()ed by the + talloc mechinism */ data_blob_clear_free(&(user->private.lm_pw)); data_blob_clear_free(&(user->private.nt_pw)); + data_blob_clear_free(&(user->private.plaintext_pw)); } @@ -519,12 +573,8 @@ BOOL pdb_rid_is_user(uint32 rid) BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use) { uint32 rid; - BOOL is_user; SAM_ACCOUNT *sam_account = NULL; - uid_t uid; - struct passwd *pass; GROUP_MAP map; - sid_peek_rid(sid, &rid); *psid_name_use = SID_NAME_UNKNOWN; @@ -564,6 +614,7 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use return False; } + /* This now does the 'generic' mapping in pdb_unix */ if (pdb_getsampwrid(sam_account, rid)) { fstrcpy(name, pdb_get_username(sam_account)); *psid_name_use = SID_NAME_USER; @@ -572,47 +623,36 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use return True; } - + pdb_free_sam(&sam_account); if (get_group_map_from_sid(*sid, &map, MAPPING_WITHOUT_PRIV)) { if (map.gid!=-1) { DEBUG(5,("local_lookup_sid: mapped group %s to gid %u\n", map.nt_name, (unsigned int)map.gid)); - fstrcpy(name, map.nt_name); - *psid_name_use = map.sid_name_use; - return True; + } else { + DEBUG(5,("local_lookup_sid: mapped group %s to no unix gid. Returning name.\n", map.nt_name)); } - } - - is_user = pdb_rid_is_user(rid); - DEBUG(5, ("assuming RID %u is a %s\n", (unsigned)rid, is_user ? "user" : "group")); + fstrcpy(name, map.nt_name); + *psid_name_use = map.sid_name_use; + return True; + } if (pdb_rid_is_user(rid)) { - uid = fallback_pdb_user_rid_to_uid(rid); - pass = getpwuid_alloc(uid); - - *psid_name_use = SID_NAME_USER; - - DEBUG(5,("local_lookup_sid: looking up uid %u %s\n", (unsigned int)uid, - pass ? "succeeded" : "failed" )); - - if(!pass) { - slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid); - return True; - } - - fstrcpy(name, pass->pw_name); - - DEBUG(5,("local_lookup_sid: found user %s for rid %u\n", name, - (unsigned int)rid )); - - passwd_free(&pass); - + uid_t uid; + + DEBUG(5, ("assuming RID %u is a user\n", (unsigned)rid)); + + uid = fallback_pdb_user_rid_to_uid(rid); + slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid); + + return False; /* Indicates that this user was 'not mapped' */ } else { gid_t gid; struct group *gr; + DEBUG(5, ("assuming RID %u is a group\n", (unsigned)rid)); + gid = pdb_group_rid_to_gid(rid); gr = getgrgid(gid); @@ -623,15 +663,15 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use if(!gr) { slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid); - return False; + return False; /* Indicates that this group was 'not mapped' */ } fstrcpy( name, gr->gr_name); DEBUG(5,("local_lookup_sid: found group %s for rid %u\n", name, (unsigned int)rid )); + return True; } - return True; } /******************************************************************* @@ -641,11 +681,12 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psid_name_use) { extern DOM_SID global_sid_World_Domain; - struct passwd *pass = NULL; DOM_SID local_sid; fstring user; SAM_ACCOUNT *sam_account = NULL; - + struct group *grp; + GROUP_MAP map; + *psid_name_use = SID_NAME_UNKNOWN; /* @@ -691,52 +732,45 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi pdb_free_sam(&sam_account); - if ((pass = Get_Pwnam(user))) { - sid_append_rid( &local_sid, fallback_pdb_uid_to_user_rid(pass->pw_uid)); - *psid_name_use = SID_NAME_USER; + /* + * Maybe it was a group ? + */ + /* check if it's a mapped group */ + if (get_group_map_from_ntname(user, &map, MAPPING_WITHOUT_PRIV)) { + if (map.gid!=-1) { + /* yes it's a mapped group to a valid unix group */ + sid_copy(&local_sid, &map.sid); + *psid_name_use = map.sid_name_use; + } + else { + /* it's a correct name but not mapped so it points to nothing*/ + return False; + } } else { - /* - * Maybe it was a group ? + /* it's not a mapped group */ + grp = getgrnam(user); + if(!grp) + return False; + + /* + *check if it's mapped, if it is reply it doesn't exist + * + * that's to prevent this case: + * + * unix group ug is mapped to nt group ng + * someone does a lookup on ug + * we must not reply as it doesn't "exist" anymore + * for NT. For NT only ng exists. + * JFM, 30/11/2001 */ - struct group *grp; - GROUP_MAP map; - /* check if it's a mapped group */ - if (get_group_map_from_ntname(user, &map, MAPPING_WITHOUT_PRIV)) { - if (map.gid!=-1) { - /* yes it's a mapped group to a valid unix group */ - sid_copy(&local_sid, &map.sid); - *psid_name_use = map.sid_name_use; - } - else - /* it's a correct name but not mapped so it points to nothing*/ - return False; - } else { - /* it's not a mapped group */ - grp = getgrnam(user); - if(!grp) - return False; - - /* - *check if it's mapped, if it is reply it doesn't exist - * - * that's to prevent this case: - * - * unix group ug is mapped to nt group ng - * someone does a lookup on ug - * we must not reply as it doesn't "exist" anymore - * for NT. For NT only ng exists. - * JFM, 30/11/2001 - */ - - if(get_group_map_from_gid(grp->gr_gid, &map, MAPPING_WITHOUT_PRIV)){ - return False; - } - - sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid)); - *psid_name_use = SID_NAME_ALIAS; + if (get_group_map_from_gid(grp->gr_gid, &map, MAPPING_WITHOUT_PRIV)){ + return False; } + + sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid)); + *psid_name_use = SID_NAME_ALIAS; } sid_copy( psid, &local_sid); @@ -824,15 +858,9 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type) DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid), (unsigned int)*puid, pdb_get_username(sam_user))); } else { - if ((pdb_rid_is_user(rid))) { - *puid = fallback_pdb_user_rid_to_uid(rid); - DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (non-passdb user).\n", sid_to_string( str, psid), - (unsigned int)*puid)); - } else { - DEBUG(5,("local_sid_to_uid: SID %s not mapped becouse RID isn't a user.\n", sid_to_string( str, psid))); - pdb_free_sam(&sam_user); - return False; - } + DEBUG(5,("local_sid_to_uid: SID %s not mapped becouse RID was not found in passdb.\n", sid_to_string( str, psid))); + pdb_free_sam(&sam_user); + return False; } pdb_free_sam(&sam_user); @@ -919,7 +947,7 @@ BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type) * @return static buffer containing the converted string **/ -static char *pdb_convert(const UNISTR2 *from) +const char *pdb_unistr2_convert(const UNISTR2 *from) { static pstring convert_buffer; *convert_buffer = 0; @@ -950,25 +978,25 @@ void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from) pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time)); if (from->uni_user_name.buffer) - pdb_set_username(to , pdb_convert(&from->uni_user_name )); + pdb_set_username(to , pdb_unistr2_convert(&from->uni_user_name )); if (from->uni_full_name.buffer) - pdb_set_fullname(to , pdb_convert(&from->uni_full_name )); + pdb_set_fullname(to , pdb_unistr2_convert(&from->uni_full_name )); if (from->uni_home_dir.buffer) - pdb_set_homedir(to , pdb_convert(&from->uni_home_dir ), True); + pdb_set_homedir(to , pdb_unistr2_convert(&from->uni_home_dir ), True); if (from->uni_dir_drive.buffer) - pdb_set_dir_drive(to , pdb_convert(&from->uni_dir_drive ), True); + pdb_set_dir_drive(to , pdb_unistr2_convert(&from->uni_dir_drive ), True); if (from->uni_logon_script.buffer) - pdb_set_logon_script(to , pdb_convert(&from->uni_logon_script), True); + pdb_set_logon_script(to , pdb_unistr2_convert(&from->uni_logon_script), True); if (from->uni_profile_path.buffer) - pdb_set_profile_path(to , pdb_convert(&from->uni_profile_path), True); + pdb_set_profile_path(to , pdb_unistr2_convert(&from->uni_profile_path), True); if (from->uni_acct_desc.buffer) - pdb_set_acct_desc(to , pdb_convert(&from->uni_acct_desc )); + pdb_set_acct_desc(to , pdb_unistr2_convert(&from->uni_acct_desc )); if (from->uni_workstations.buffer) - pdb_set_workstations(to , pdb_convert(&from->uni_workstations)); + pdb_set_workstations(to , pdb_unistr2_convert(&from->uni_workstations)); if (from->uni_unknown_str.buffer) - pdb_set_unknown_str(to , pdb_convert(&from->uni_unknown_str )); + pdb_set_unknown_str(to , pdb_unistr2_convert(&from->uni_unknown_str )); if (from->uni_munged_dial.buffer) - pdb_set_munged_dial(to , pdb_convert(&from->uni_munged_dial )); + pdb_set_munged_dial(to , pdb_unistr2_convert(&from->uni_munged_dial )); if (from->user_rid) pdb_set_user_rid(to, from->user_rid); @@ -1005,25 +1033,25 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time)); if (from->uni_user_name.buffer) - pdb_set_username(to , pdb_convert(&from->uni_user_name )); + pdb_set_username(to , pdb_unistr2_convert(&from->uni_user_name )); if (from->uni_full_name.buffer) - pdb_set_fullname(to , pdb_convert(&from->uni_full_name )); + pdb_set_fullname(to , pdb_unistr2_convert(&from->uni_full_name )); if (from->uni_home_dir.buffer) - pdb_set_homedir(to , pdb_convert(&from->uni_home_dir ), True); + pdb_set_homedir(to , pdb_unistr2_convert(&from->uni_home_dir ), True); if (from->uni_dir_drive.buffer) - pdb_set_dir_drive(to , pdb_convert(&from->uni_dir_drive ), True); + pdb_set_dir_drive(to , pdb_unistr2_convert(&from->uni_dir_drive ), True); if (from->uni_logon_script.buffer) - pdb_set_logon_script(to , pdb_convert(&from->uni_logon_script), True); + pdb_set_logon_script(to , pdb_unistr2_convert(&from->uni_logon_script), True); if (from->uni_profile_path.buffer) - pdb_set_profile_path(to , pdb_convert(&from->uni_profile_path), True); + pdb_set_profile_path(to , pdb_unistr2_convert(&from->uni_profile_path), True); if (from->uni_acct_desc.buffer) - pdb_set_acct_desc(to , pdb_convert(&from->uni_acct_desc )); + pdb_set_acct_desc(to , pdb_unistr2_convert(&from->uni_acct_desc )); if (from->uni_workstations.buffer) - pdb_set_workstations(to , pdb_convert(&from->uni_workstations)); + pdb_set_workstations(to , pdb_unistr2_convert(&from->uni_workstations)); if (from->uni_unknown_str.buffer) - pdb_set_unknown_str(to , pdb_convert(&from->uni_unknown_str )); + pdb_set_unknown_str(to , pdb_unistr2_convert(&from->uni_unknown_str )); if (from->uni_munged_dial.buffer) - pdb_set_munged_dial(to , pdb_convert(&from->uni_munged_dial )); + pdb_set_munged_dial(to , pdb_unistr2_convert(&from->uni_munged_dial )); if (from->user_rid) pdb_set_user_rid(to, from->user_rid); diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index cf77efd38f..372b332a45 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -138,6 +138,21 @@ const uint8* pdb_get_lanman_passwd (const SAM_ACCOUNT *sampass) return (NULL); } +/* Return the plaintext password if known. Most of the time + it isn't, so don't assume anything magic about this function. + + Used to pass the plaintext to passdb backends that might + want to store more than just the NTLM hashes. +*/ +const char* pdb_get_plaintext_passwd (const SAM_ACCOUNT *sampass) +{ + if (sampass) { + return ((char*)sampass->private.plaintext_pw.data); + } + else + return (NULL); +} + uint32 pdb_get_user_rid (const SAM_ACCOUNT *sampass) { if (sampass) @@ -224,6 +239,14 @@ const char* pdb_get_homedir (const SAM_ACCOUNT *sampass) return (NULL); } +const char* pdb_get_unix_homedir (const SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->private.unix_home_dir); + else + return (NULL); +} + const char* pdb_get_dirdrive (const SAM_ACCOUNT *sampass) { if (sampass) @@ -618,7 +641,7 @@ BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, const char *logon_script, BOOL s } if (store) { - DEBUG(10, ("pdb_set_logon_script: setting logon script sam flag!")); + DEBUG(10, ("pdb_set_logon_script: setting logon script sam flag!\n")); pdb_set_init_flag(sampass, FLAG_SAM_LOGONSCRIPT); } @@ -650,7 +673,7 @@ BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, const char *profile_path, BOOL } if (store) { - DEBUG(10, ("pdb_set_profile_path: setting profile path sam flag!")); + DEBUG(10, ("pdb_set_profile_path: setting profile path sam flag!\n")); pdb_set_init_flag(sampass, FLAG_SAM_PROFILE); } @@ -682,7 +705,7 @@ BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, const char *dir_drive, BOOL store) } if (store) { - DEBUG(10, ("pdb_set_dir_drive: setting dir drive sam flag!")); + DEBUG(10, ("pdb_set_dir_drive: setting dir drive sam flag!\n")); pdb_set_init_flag(sampass, FLAG_SAM_DRIVE); } @@ -722,6 +745,34 @@ BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, const char *home_dir, BOOL store) } /********************************************************************* + Set the user's unix home directory. + ********************************************************************/ + +BOOL pdb_set_unix_homedir (SAM_ACCOUNT *sampass, const char *unix_home_dir) +{ + if (!sampass) + return False; + + if (unix_home_dir) { + DEBUG(10, ("pdb_set_homedir: setting home dir %s, was %s\n", unix_home_dir, + (sampass->private.unix_home_dir)?(sampass->private.unix_home_dir):"NULL")); + + sampass->private.unix_home_dir = talloc_strdup(sampass->mem_ctx, + unix_home_dir); + + if (!sampass->private.unix_home_dir) { + DEBUG(0, ("pdb_set_unix_home_dir: talloc_strdup() failed!\n")); + return False; + } + + } else { + sampass->private.unix_home_dir = PDB_NOT_QUITE_NULL; + } + + return True; +} + +/********************************************************************* Set the user's account description. ********************************************************************/ @@ -840,7 +891,7 @@ BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, const uint8 *pwd) Set the user's LM hash. ********************************************************************/ -BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 *pwd) +BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[16]) { if (!sampass) return False; @@ -852,6 +903,23 @@ BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 *pwd) return True; } +/********************************************************************* + Set the user's plaintext password only (base procedure, see helper + below) + ********************************************************************/ + +BOOL pdb_set_plaintext_pw_only (SAM_ACCOUNT *sampass, const uint8 *password, size_t len) +{ + if (!sampass) + return False; + + data_blob_clear_free(&sampass->private.plaintext_pw); + + sampass->private.plaintext_pw = data_blob(password, len); + + return True; +} + BOOL pdb_set_unknown_3 (SAM_ACCOUNT *sampass, uint32 unkn) { if (!sampass) diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index a19bf254e7..6488decf94 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -30,6 +30,7 @@ const struct pdb_init_function_entry builtin_pdb_init_functions[] = { { "tdbsam_nua", pdb_init_tdbsam_nua }, { "ldapsam", pdb_init_ldapsam }, { "ldapsam_nua", pdb_init_ldapsam_nua }, + { "unixsam", pdb_init_unixsam }, { "plugin", pdb_init_plugin }, { NULL, NULL} }; @@ -42,7 +43,12 @@ static BOOL context_setsampwent(struct pdb_context *context, BOOL update) } context->pwent_methods = context->pdb_methods; - + + if (!context->pwent_methods) { + /* No passdbs at all */ + return True; + } + while(!(context->pwent_methods->setsampwent(context->pwent_methods, update))){ context->pwent_methods = context->pwent_methods->next; if(context->pwent_methods == NULL)return False; @@ -83,7 +89,7 @@ static BOOL context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user) if(context->pwent_methods == NULL)return False; if(!context->pwent_methods->setsampwent){ - DEBUG(0, ("invalid context->pwent_methods->setsampwent\n")); + DEBUG(5, ("invalid context->pwent_methods->setsampwent\n")); return False; } @@ -251,7 +257,11 @@ static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_c if (!*methods) { DEBUG(0,("failed to select passdb backed!\n")); - return nt_status; + if (NT_STATUS_IS_OK(nt_status)) { + return NT_STATUS_INVALID_PARAMETER; + } else { + return nt_status; + } } return NT_STATUS_OK; } diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index af0cbef4f2..9614483ee1 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -339,7 +339,7 @@ static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state, search an attribute and return the first value found. ******************************************************************/ static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, - char *attribute, char *value) + char *attribute, pstring value) { char **values; @@ -521,12 +521,14 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pw = getpwnam_alloc(username); if (pw == NULL) { - DEBUG (2,("init_sam_from_ldap: User [%s] does not have a uid!\n", username)); + DEBUG (2,("init_sam_from_ldap: User [%s] does not ave a uid!\n", username)); return False; } uid = pw->pw_uid; gid = pw->pw_gid; + pdb_set_unix_homedir(sampass, pw->pw_dir); + passwd_free(&pw); pdb_set_uid(sampass, uid); @@ -603,37 +605,41 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive)) { - pstrcpy(dir_drive, lp_logon_drive()); - standard_sub_advanced(-1, username, "", gid, username, dir_drive); - DEBUG(5,("homeDrive fell back to %s\n",dir_drive)); - pdb_set_dir_drive(sampass, dir_drive, False); + pdb_set_dir_drive(sampass, standard_sub_specified(sampass->mem_ctx, + lp_logon_path(), + username, domain, + uid, gid), + False); } else { pdb_set_dir_drive(sampass, dir_drive, True); } if (!get_single_attribute(ldap_struct, entry, "smbHome", homedir)) { - pstrcpy(homedir, lp_logon_home()); - standard_sub_advanced(-1, username, "", gid, username, homedir); - DEBUG(5,("smbHome fell back to %s\n",homedir)); - pdb_set_homedir(sampass, homedir, False); + pdb_set_dir_drive(sampass, standard_sub_specified(sampass->mem_ctx, + lp_logon_home(), + username, domain, + uid, gid), + False); } else { pdb_set_homedir(sampass, homedir, True); } if (!get_single_attribute(ldap_struct, entry, "scriptPath", logon_script)) { - pstrcpy(logon_script, lp_logon_script()); - standard_sub_advanced(-1, username, "", gid, username, logon_script); - DEBUG(5,("scriptPath fell back to %s\n",logon_script)); - pdb_set_logon_script(sampass, logon_script, False); + pdb_set_logon_script(sampass, standard_sub_specified(sampass->mem_ctx, + lp_logon_script(), + username, domain, + uid, gid), + False); } else { pdb_set_logon_script(sampass, logon_script, True); } if (!get_single_attribute(ldap_struct, entry, "profilePath", profile_path)) { - pstrcpy(profile_path, lp_logon_path()); - standard_sub_advanced(-1, username, "", gid, username, profile_path); - DEBUG(5,("profilePath fell back to %s\n",profile_path)); - pdb_set_profile_path(sampass, profile_path, False); + pdb_set_profile_path(sampass, standard_sub_specified(sampass->mem_ctx, + lp_logon_path(), + username, domain, + uid, gid), + False); } else { pdb_set_profile_path(sampass, profile_path, True); } @@ -740,7 +746,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, } else if (ldap_state->permit_non_unix_accounts) { rid = ldapsam_get_next_available_nua_rid(ldap_state); if (rid == 0) { - DEBUG(0, ("NO user RID specified on account %s, and finding next available NUA RID failed, cannot store!\n", pdb_get_username(sampass))); + DEBUG(0, ("NO user RID specified on account %s, and findining next available NUA RID failed, cannot store!\n", pdb_get_username(sampass))); return False; } } else { @@ -1097,7 +1103,7 @@ static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * us if (ldap_count_entries(ldap_struct, result) < 1) { DEBUG(4, - ("We didn't find the user [%s] count=%d\n", sname, + ("We don't find this user [%s] count=%d\n", sname, ldap_count_entries(ldap_struct, result))); ldap_unbind(ldap_struct); return False; @@ -1151,7 +1157,7 @@ static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * us if (ldap_count_entries(ldap_struct, result) < 1) { DEBUG(0, - ("We didn't find the rid [%i] count=%d\n", rid, + ("We don't find this rid [%i] count=%d\n", rid, ldap_count_entries(ldap_struct, result))); ldap_unbind(ldap_struct); return False; @@ -1205,7 +1211,7 @@ static BOOL ldapsam_delete_sam_account(struct pdb_methods *my_methods, const SAM if (!ldapsam_connect_system(ldap_state, ldap_struct)) { ldap_unbind (ldap_struct); - DEBUG(0, ("failed to delete user %s from the LDAP database.\n", sname)); + DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname)); return False; } diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 9f37cadfe8..88e317cea9 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -1218,7 +1218,8 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas /********************************************************************* Create a SAM_ACCOUNT from a smb_passwd struct ********************************************************************/ -static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf) +static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, + SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf) { struct passwd *pwfile; @@ -1242,73 +1243,25 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, SAM_AC } else { - uint32 grid; - GROUP_MAP map; - - /* Verify in system password file... - FIXME!!! This is where we should look up an internal - mapping of allocated uid for machine accounts as well - --jerry */ pwfile = getpwnam_alloc(pw_buf->smb_name); if (pwfile == NULL) { DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s with uid %u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid)); return False; } - pdb_set_uid (sam_pass, pwfile->pw_uid); - pdb_set_gid (sam_pass, pwfile->pw_gid); - - pdb_set_fullname(sam_pass, pwfile->pw_gecos); - - pdb_set_user_rid(sam_pass, fallback_pdb_uid_to_user_rid (pwfile->pw_uid)); - - if (get_group_map_from_gid(pwfile->pw_gid, &map, MAPPING_WITHOUT_PRIV)) { - sid_peek_rid(&map.sid, &grid); - } else { - grid=pdb_gid_to_group_rid(pwfile->pw_gid); - } - - pdb_set_group_rid(sam_pass, grid); - - /* check if this is a user account or a machine account */ - if (pw_buf->smb_name[strlen(pw_buf->smb_name)-1] != '$') - { - pstring str; - - pstrcpy(str, lp_logon_path()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_profile_path(sam_pass, str, False); - - pstrcpy(str, lp_logon_home()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_homedir(sam_pass, str, False); - - pstrcpy(str, lp_logon_drive()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_dir_drive(sam_pass, str, False); - - pstrcpy(str, lp_logon_script()); - standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str); - pdb_set_logon_script(sam_pass, str, False); - - } else { - /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ - /*pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS); */ + if (!NT_STATUS_IS_OK(pdb_fill_sam_pw(sam_pass, pwfile))) { + return False; } passwd_free(&pwfile); } - pdb_set_username (sam_pass, pw_buf->smb_name); pdb_set_nt_passwd (sam_pass, pw_buf->smb_nt_passwd); pdb_set_lanman_passwd (sam_pass, pw_buf->smb_passwd); pdb_set_acct_ctrl (sam_pass, pw_buf->acct_ctrl); pdb_set_pass_last_set_time (sam_pass, pw_buf->pass_last_set_time); pdb_set_pass_can_change_time (sam_pass, pw_buf->pass_last_set_time, True); - pdb_set_domain (sam_pass, lp_workgroup()); - pdb_set_dir_drive (sam_pass, lp_logon_drive(), False); - #if 0 /* JERRY */ /* the smbpasswd format doesn't have a must change time field, so we can't get this right. The best we can do is to set this to diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index 3a9bc894bb..46120c3ccc 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -86,12 +86,11 @@ static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, uint8 *hours; static uint8 *lm_pw_ptr, *nt_pw_ptr; uint32 len = 0; - uint32 lmpwlen, ntpwlen, hourslen; + uint32 lm_pw_len, nt_pw_len, hourslen; BOOL ret = True; - BOOL setflag; pstring sub_buffer; struct passwd *pw; - uid_t uid; + uid_t uid = -1; gid_t gid = -1; /* This is what standard sub advanced expects if no gid is known */ if(sampass == NULL || buf == NULL) { @@ -121,8 +120,8 @@ static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, &munged_dial_len, &munged_dial, &user_rid, &group_rid, - &lmpwlen, &lm_pw_ptr, - &ntpwlen, &nt_pw_ptr, + &lm_pw_len, &lm_pw_ptr, + &nt_pw_len, &nt_pw_ptr, &acct_ctrl, &unknown_3, &logon_divs, @@ -152,6 +151,8 @@ static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, uid = pw->pw_uid; gid = pw->pw_gid; + pdb_set_unix_homedir(sampass, pw->pw_dir); + passwd_free(&pw); pdb_set_uid(sampass, uid); @@ -165,66 +166,72 @@ static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, pdb_set_pass_must_change_time(sampass, pass_must_change_time, True); pdb_set_pass_last_set_time(sampass, pass_last_set_time); - pdb_set_username (sampass, username); + pdb_set_username (sampass, username); pdb_set_domain (sampass, domain); pdb_set_nt_username (sampass, nt_username); pdb_set_fullname (sampass, fullname); - if (homedir) setflag = True; + if (homedir) { + pdb_set_homedir(sampass, homedir, True); + } else { - setflag = False; - pstrcpy(sub_buffer, lp_logon_home()); - /* standard_sub_advanced() assumes pstring is passed!! */ - standard_sub_advanced(-1, username, "", gid, username, sub_buffer); - homedir = strdup(sub_buffer); - if(!homedir) { ret = False; goto done; } - DEBUG(5,("Home directory set back to %s\n", homedir)); + pdb_set_homedir(sampass, + standard_sub_specified(sampass->mem_ctx, + lp_logon_home(), + username, domain, + uid, gid), + False); } - pdb_set_homedir(sampass, homedir, setflag); - if (dir_drive) setflag = True; + if (dir_drive) + pdb_set_dir_drive(sampass, dir_drive, True); else { - setflag = False; - pstrcpy(sub_buffer, lp_logon_drive()); - standard_sub_advanced(-1, username, "", gid, username, sub_buffer); - dir_drive = strdup(sub_buffer); - if(!dir_drive) { ret = False; goto done; } - DEBUG(5,("Drive set back to %s\n", dir_drive)); + pdb_set_dir_drive(sampass, + standard_sub_specified(sampass->mem_ctx, + lp_logon_drive(), + username, domain, + uid, gid), + False); } - pdb_set_dir_drive(sampass, dir_drive, setflag); - if (logon_script) setflag = True; + if (logon_script) + pdb_set_logon_script(sampass, logon_script, True); else { - setflag = False; - pstrcpy(sub_buffer, lp_logon_script()); - standard_sub_advanced(-1, username, "", gid, username, sub_buffer); - logon_script = strdup(sub_buffer); - if(!logon_script) { ret = False; goto done; } - DEBUG(5,("Logon script set back to %s\n", logon_script)); + pdb_set_logon_script(sampass, + standard_sub_specified(sampass->mem_ctx, + lp_logon_script(), + username, domain, + uid, gid), + False); } - pdb_set_logon_script(sampass, logon_script, setflag); - if (profile_path) setflag = True; - else { - setflag = False; - pstrcpy(sub_buffer, lp_logon_path()); - standard_sub_advanced(-1, username, "", gid, username, sub_buffer); - profile_path = strdup(sub_buffer); - if(!profile_path) { ret = False; goto done; } - DEBUG(5,("Profile path set back to %s\n", profile_path)); + if (profile_path) { + pdb_set_profile_path(sampass, profile_path, True); + } else { + pdb_set_profile_path(sampass, + standard_sub_specified(sampass->mem_ctx, + lp_logon_path(), + username, domain, + uid, gid), + False); } - pdb_set_profile_path(sampass, profile_path, setflag); pdb_set_acct_desc (sampass, acct_desc); pdb_set_workstations (sampass, workstations); pdb_set_munged_dial (sampass, munged_dial); - if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr)) { - ret = False; - goto done; + + if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) { + if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr)) { + ret = False; + goto done; + } } - if (!pdb_set_nt_passwd(sampass, nt_pw_ptr)) { - ret = False; - goto done; + + if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) { + if (!pdb_set_nt_passwd(sampass, nt_pw_ptr)) { + ret = False; + goto done; + } } pdb_set_user_rid(sampass, user_rid); diff --git a/source3/passdb/pdb_unix.c b/source3/passdb/pdb_unix.c new file mode 100644 index 0000000000..d1f95c445b --- /dev/null +++ b/source3/passdb/pdb_unix.c @@ -0,0 +1,126 @@ +/* + * Unix password backend for samba + * Copyright (C) Jelmer Vernooij 2002 + * + * 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 the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 675 + * Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/****************************************************************** + Lookup a name in the SAM database + ******************************************************************/ + +static BOOL unixsam_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname) +{ + struct passwd *pass; + if (!methods) { + DEBUG(0,("invalid methods\n")); + return False; + } + if (!sname) { + DEBUG(0,("invalid name specified")); + return False; + } + pass = Get_Pwnam(sname); + + return NT_STATUS_IS_OK(pdb_fill_sam_pw(user, pass)); +} + + +/*************************************************************************** + Search by rid + **************************************************************************/ + +static BOOL unixsam_getsampwrid (struct pdb_methods *methods, + SAM_ACCOUNT *user, uint32 rid) +{ + struct passwd *pass; + BOOL ret = False; + if (!methods) { + DEBUG(0,("invalid methods\n")); + return False; + } + + if (pdb_rid_is_user(rid)) { + pass = getpwuid_alloc(fallback_pdb_user_rid_to_uid (rid)); + + if (pass) { + ret = NT_STATUS_IS_OK(pdb_fill_sam_pw(user, pass)); + passwd_free(&pass); + } + } + return ret; +} + +/*************************************************************************** + Delete a SAM_ACCOUNT + ****************************************************************************/ + +static BOOL unixsam_delete_sam_account(struct pdb_methods *methods, const SAM_ACCOUNT *sam_pass) +{ + /* + * Unsupported as well - we don't need to get involved in + * unix passdb's - and hey, we would need to use pam for that anyway + */ + return False; +} + +/*************************************************************************** + Modifies an existing SAM_ACCOUNT + ****************************************************************************/ + +static BOOL unixsam_update_sam_account (struct pdb_methods *methods, const SAM_ACCOUNT *newpwd) +{ + return False; +} + +/*************************************************************************** + Adds an existing SAM_ACCOUNT + ****************************************************************************/ + +static BOOL unixsam_add_sam_account (struct pdb_methods *methods, const SAM_ACCOUNT *newpwd) +{ + DEBUG(0,("pdb_unix should not be listed as the first passdb backend! You can't add users to it.\n")); + return False; +} + +NTSTATUS pdb_init_unixsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS nt_status; + + if (!pdb_context) { + DEBUG(0, ("invalid pdb_context specified\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { + return nt_status; + } + + (*pdb_method)->name = "unixsam"; + + (*pdb_method)->setsampwent = NULL; + (*pdb_method)->endsampwent = NULL; + (*pdb_method)->getsampwent = NULL; + (*pdb_method)->getsampwnam = unixsam_getsampwnam; + (*pdb_method)->getsampwrid = unixsam_getsampwrid; + (*pdb_method)->add_sam_account = unixsam_add_sam_account; + (*pdb_method)->update_sam_account = unixsam_update_sam_account; + (*pdb_method)->delete_sam_account = unixsam_delete_sam_account; + + /* There's not very much to initialise here */ + return NT_STATUS_OK; +} diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index b8a558665f..66312db52e 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -1462,13 +1462,30 @@ NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_en ZERO_STRUCTP(sam->str); for (i = 0; i < num_entries ; i++) { + const char *username; + const char *fullname; + const char *acct_desc; + DEBUG(11, ("init_sam_dispinfo_1: entry: %d\n",i)); pwd=disp_user_info[i+start_idx].sam; - len_sam_name = strlen(pdb_get_username(pwd)); - len_sam_full = strlen(pdb_get_fullname(pwd)); - len_sam_desc = strlen(pdb_get_acct_desc(pwd)); + username = pdb_get_username(pwd); + fullname = pdb_get_fullname(pwd); + acct_desc = pdb_get_acct_desc(pwd); + + if (!username) + username = ""; + + if (!fullname) + fullname = ""; + + if (!acct_desc) + acct_desc = ""; + + len_sam_name = strlen(username); + len_sam_full = strlen(fullname); + len_sam_desc = strlen(acct_desc); init_sam_entry1(&sam->sam[i], start_idx + i + 1, len_sam_name, len_sam_full, len_sam_desc, diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index c4adc26360..a5e3f5003c 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -259,6 +259,8 @@ static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME if (!status) { sid_name_use = SID_NAME_UNKNOWN; + } else { + (*mapped_count)++; } /* Store domain sid in ref array */ @@ -272,8 +274,6 @@ static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME 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++; diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index 9b0aa360bc..c701ed41cd 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -72,6 +72,11 @@ END { printf "char *%s(int );\n", a[2] } +/^FN_LOCAL_CONST_STRING/ { + split($0,a,"[,()]") + printf "const char *%s(int );\n", a[2] +} + /^FN_LOCAL_INT/ { split($0,a,"[,()]") printf "int %s(int );\n", a[2] @@ -97,6 +102,11 @@ END { printf "char *%s(void);\n", a[2] } +/^FN_GLOBAL_CONST_STRING/ { + split($0,a,"[,()]") + printf "const char *%s(void);\n", a[2] +} + /^FN_GLOBAL_INT/ { split($0,a,"[,()]") printf "int %s(void);\n", a[2] diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index f8875c5c0f..5585097c91 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1933,7 +1933,7 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch while ( pdb_getsampwent(pwd) ) { const char *name=pdb_get_username(pwd); - if( *(name+strlen(name)-1)!='$' ) { + if ((name) && (*(name+strlen(name)-1)!='$')) { count_total++; if(count_total>=resume_context) { if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) { @@ -2793,8 +2793,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ - pstrcpy(p2, lp_logon_home()); - standard_sub_conn(conn, p2); + pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); p2 = skip_string(p2,1); SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ pstrcpy(p2,""); @@ -2830,15 +2829,13 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(p,42, conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - pstrcpy(p2,lp_logon_home()); - standard_sub_conn(conn, p2); + pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; SSVAL(p,52,0); /* flags */ SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ - pstrcpy(p2,lp_logon_script()); - standard_sub_conn( conn, p2 ); + pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : ""); p2 = skip_string(p2,1); if (uLevel == 2) { @@ -2888,6 +2885,12 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param int uLevel; struct pack_desc desc; char* name; + /* With share level security vuid will always be zero. + Don't depend on vuser being non-null !!. JRA */ + user_struct *vuser = get_valid_user_struct(vuid); + if(vuser != NULL) + DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, + vuser->user.unix_name)); uLevel = SVAL(p,0); name = p + 2; @@ -2931,15 +2934,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param } PACKS(&desc,"z",global_myworkgroup);/* domain */ -/* JHT - By calling lp_logon_script() and standard_sub() we have */ -/* made sure all macros are fully substituted and available */ - { - pstring logon_script; - pstrcpy(logon_script,lp_logon_script()); - standard_sub_conn( conn, logon_script ); - PACKS(&desc,"z", logon_script); /* script path */ - } -/* End of JHT mods */ + PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */ PACKI(&desc,"D",0x00000000); /* reserved */ } @@ -3458,7 +3453,7 @@ static int gather_sessioninfo(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo { struct sessions_info *sinfo = state; struct session_info *curinfo = NULL; - struct sessionid *sessid = (struct sessionid *) dbuf.dptr; + const struct sessionid *sessid = (const struct sessionid *) dbuf.dptr; sinfo->count += 1; sinfo->session_list = REALLOC(sinfo->session_list, sinfo->count * sizeof(struct session_info)); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 629157f22d..a8fd2b47f1 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -259,9 +259,19 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) { /* Keep the homedir handy */ const char *homedir = pdb_get_homedir(server_info->sam_account); + const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); + const char *logon_script = pdb_get_logon_script(server_info->sam_account); if (homedir) { vuser->homedir = smb_xstrdup(homedir); } + + if (unix_homedir) { + vuser->unix_homedir = smb_xstrdup(unix_homedir); + } + + if (logon_script) { + vuser->logon_script = smb_xstrdup(logon_script); + } } memcpy(vuser->session_key, server_info->session_key, sizeof(vuser->session_key)); @@ -301,9 +311,9 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name) } /* Register a home dir service for this user */ - if ((!vuser->guest) && vuser->homedir && *(vuser->homedir) + if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir) && (lp_servicenumber(vuser->user.unix_name) < 0)) { - add_home_service(vuser->user.unix_name, vuser->homedir); + add_home_service(vuser->user.unix_name, vuser->unix_homedir); } return vuser->vuid; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 467bab4a0a..32ceb63154 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -81,9 +81,6 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir) int add_home_service(const char *service, const char *homedir) { int iHomeService; - int iService; - fstring new_service; - fstring domain; if (!service || !homedir) return -1; @@ -98,11 +95,19 @@ int add_home_service(const char *service, const char *homedir) * include any macros. */ - split_domain_and_name(service, domain, new_service); - lp_add_home(new_service, iHomeService, homedir); - iService = lp_servicenumber(new_service); + { + const char *p = strchr(service,*lp_winbind_separator()); + + /* We only want the 'user' part of the string */ + if (p) { + service = p + 1; + } + } + + lp_add_home(service, iHomeService, homedir); + + return lp_servicenumber(service); - return iService; } diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index c4558ea10b..cc1a203ca1 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -53,7 +53,6 @@ int net_rpc_join_newstyle(int argc, const char **argv) /* libsmb variables */ struct cli_state *cli; - fstring acct_name; TALLOC_CTX *mem_ctx; uint32 acb_info; @@ -81,7 +80,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) fstring domain; uint32 num_rids, *name_types, *user_rids; uint32 flags = 0x3e8; - char *names; + const char *acct_name; /* Connect to remote machine */ @@ -132,8 +131,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) "could not open domain"); /* Create domain user */ - fstrcpy(acct_name, global_myname); - fstrcat(acct_name, "$"); + acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname); strlower(acct_name); acb_info = ((lp_server_role() == ROLE_DOMAIN_BDC) || lp_server_role() == ROLE_DOMAIN_PDC) ? ACB_SVRTRUST : ACB_WSTRUST; @@ -162,11 +160,9 @@ int net_rpc_join_newstyle(int argc, const char **argv) if (NT_STATUS_IS_OK(result)) cli_samr_close(cli, mem_ctx, &user_pol); - names = (char *)&acct_name[0]; - CHECK_RPC_ERR_DEBUG(cli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, - 1, &names, &num_rids, + 1, &acct_name, &num_rids, &user_rids, &name_types), ("error looking up rid for user %s: %s\n", acct_name, nt_errstr(result))); |