📄 pdb_smbpasswd.c
字号:
DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile)); return False; } /* * Create the replacement password file. */ if((fp_write = startsmbfilepwent(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) { DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile)); endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth); return False; } /* * Scan the file, a line at a time and check if the name matches. */ while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) { char *new_entry; size_t new_entry_length; if (strequal(name, pwd->smb_name)) { DEBUG(10, ("add_smbfilepwd_entry: found entry with name %s - deleting it.\n", name)); continue; } /* * We need to copy the entry out into the second file. */ if((new_entry = format_new_smbpasswd_entry(pwd)) == NULL) { DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); unlink(pfile2); endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth); endsmbfilepwent(fp_write, &pfile2_lockdepth); return False; } new_entry_length = strlen(new_entry); if(fwrite(new_entry, 1, new_entry_length, fp_write) != new_entry_length) { DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); unlink(pfile2); endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth); endsmbfilepwent(fp_write, &pfile2_lockdepth); free(new_entry); return False; } free(new_entry); } /* * Ensure pfile2 is flushed before rename. */ if(fflush(fp_write) != 0) { DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno))); endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth); endsmbfilepwent(fp_write,&pfile2_lockdepth); return False; } /* * Do an atomic rename - then release the locks. */ if(rename(pfile2,pfile) != 0) { unlink(pfile2); } endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth); endsmbfilepwent(fp_write,&pfile2_lockdepth); return True;}/********************************************************************* Create a smb_passwd struct from a SAM_ACCOUNT. We will not allocate any new memory. The smb_passwd struct should only stay around as long as the SAM_ACCOUNT does. ********************************************************************/static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampass){ uint32 rid; if (sampass == NULL) return False; ZERO_STRUCTP(smb_pw); if (!IS_SAM_DEFAULT(sampass, PDB_USERSID)) { rid = pdb_get_user_rid(sampass); /* If the user specified a RID, make sure its able to be both stored and retreived */ if (rid == DOMAIN_USER_RID_GUEST) { struct passwd *passwd = getpwnam_alloc(lp_guestaccount()); if (!passwd) { DEBUG(0, ("Could not find gest account via getpwnam()! (%s)\n", lp_guestaccount())); return False; } smb_pw->smb_userid=passwd->pw_uid; passwd_free(&passwd); } else if (algorithmic_pdb_rid_is_user(rid)) { smb_pw->smb_userid=algorithmic_pdb_user_rid_to_uid(rid); } else { DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n")); return False; } } smb_pw->smb_name=(const char*)pdb_get_username(sampass); smb_pw->smb_passwd=pdb_get_lanman_passwd(sampass); smb_pw->smb_nt_passwd=pdb_get_nt_passwd(sampass); smb_pw->acct_ctrl=pdb_get_acct_ctrl(sampass); smb_pw->pass_last_set_time=pdb_get_pass_last_set_time(sampass); return True;} /********************************************************************* 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){ struct passwd *pwfile; if (sam_pass==NULL) { DEBUG(5,("build_sam_account: SAM_ACCOUNT is NULL\n")); return False; } /* verify the user account exists */ if ( !(pwfile = getpwnam_alloc(pw_buf->smb_name)) ) { 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; } if (!NT_STATUS_IS_OK(pdb_fill_sam_pw(sam_pass, pwfile))) return False; passwd_free(&pwfile); /* set remaining fields */ pdb_set_nt_passwd (sam_pass, pw_buf->smb_nt_passwd, PDB_SET); pdb_set_lanman_passwd (sam_pass, pw_buf->smb_passwd, PDB_SET); pdb_set_acct_ctrl (sam_pass, pw_buf->acct_ctrl, PDB_SET); pdb_set_pass_last_set_time (sam_pass, pw_buf->pass_last_set_time, PDB_SET); pdb_set_pass_can_change_time (sam_pass, pw_buf->pass_last_set_time, PDB_SET); return True;}/***************************************************************** Functions to be implemented by the new passdb API ****************************************************************/static NTSTATUS smbpasswd_setsampwent (struct pdb_methods *my_methods, BOOL update, uint16 acb_mask){ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file, update ? PWF_UPDATE : PWF_READ, &(smbpasswd_state->pw_file_lock_depth)); /* did we fail? Should we try to create it? */ if (!smbpasswd_state->pw_file && update && errno == ENOENT) { FILE *fp; /* slprintf(msg_str,msg_str_len-1, "smbpasswd file did not exist - attempting to create it.\n"); */ DEBUG(0,("smbpasswd file did not exist - attempting to create it.\n")); fp = sys_fopen(smbpasswd_state->smbpasswd_file, "w"); if (fp) { fprintf(fp, "# Samba SMB password file\n"); fclose(fp); } smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file, update ? PWF_UPDATE : PWF_READ, &(smbpasswd_state->pw_file_lock_depth)); } if (smbpasswd_state->pw_file != NULL) return NT_STATUS_OK; else return NT_STATUS_UNSUCCESSFUL; }static void smbpasswd_endsampwent (struct pdb_methods *my_methods){ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; endsmbfilepwent(smbpasswd_state->pw_file, &(smbpasswd_state->pw_file_lock_depth));} /***************************************************************** ****************************************************************/static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user){ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd *pw_buf=NULL; BOOL done = False; DEBUG(5,("pdb_getsampwent\n")); if (user==NULL) { DEBUG(5,("pdb_getsampwent (smbpasswd): user is NULL\n"));#if 0 smb_panic("NULL pointer passed to getsampwent (smbpasswd)\n");#endif return nt_status; } while (!done) { /* do we have an entry? */ pw_buf = getsmbfilepwent(smbpasswd_state, smbpasswd_state->pw_file); if (pw_buf == NULL) return nt_status; /* build the SAM_ACCOUNT entry from the smb_passwd struct. We loop in case the user in the pdb does not exist in the local system password file */ if (build_sam_account(smbpasswd_state, user, pw_buf)) done = True; } DEBUG(5,("getsampwent (smbpasswd): done\n")); /* success */ return NT_STATUS_OK;}/**************************************************************** Search smbpasswd file by iterating over the entries. Do not call getpwnam() for unix account information until we have found the correct entry ***************************************************************/static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_acct, const char *username){ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd *smb_pw; void *fp = NULL; DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username)); /* startsmbfilepwent() is used here as we don't want to lookup the UNIX account in the local system password file until we have a match. */ fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth)); if (fp == NULL) { DEBUG(0, ("Unable to open passdb database.\n")); return nt_status; } while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) ) /* do nothing....another loop */ ; endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); /* did we locate the username in smbpasswd */ if (smb_pw == NULL) return nt_status; DEBUG(10, ("getsampwnam (smbpasswd): found by name: %s\n", smb_pw->smb_name)); if (!sam_acct) { DEBUG(10,("getsampwnam (smbpasswd): SAM_ACCOUNT is NULL\n"));#if 0 smb_panic("NULL pointer passed to pdb_getsampwnam\n");#endif return nt_status; } /* now build the SAM_ACCOUNT */ if (!build_sam_account(smbpasswd_state, sam_acct, smb_pw)) return nt_status; /* success */ return NT_STATUS_OK;}static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_acct, const DOM_SID *sid){ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd *smb_pw; void *fp = NULL; fstring sid_str; uint32 rid; DEBUG(10, ("smbpasswd_getsampwrid: search by sid: %s\n", sid_to_string(sid_str, sid))); if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) return NT_STATUS_UNSUCCESSFUL; /* More special case 'guest account' hacks... */ if (rid == DOMAIN_USER_RID_GUEST) { const char *guest_account = lp_guestaccount(); if (!(guest_account && *guest_account)) { DEBUG(1, ("Guest account not specfied!\n")); return nt_status; } return smbpasswd_getsampwnam(my_methods, sam_acct, guest_account); } /* Open the sam password file - not for update. */ fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth)); if (fp == NULL) { DEBUG(0, ("Unable to open passdb database.\n")); return nt_status; } while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL) && (algorithmic_pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) ) /* do nothing */ ; endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); /* did we locate the username in smbpasswd */ if (smb_pw == NULL) return nt_status; DEBUG(10, ("getsampwrid (smbpasswd): found by name: %s\n", smb_pw->smb_name)); if (!sam_acct) { DEBUG(10,("getsampwrid: (smbpasswd) SAM_ACCOUNT is NULL\n"));#if 0 smb_panic("NULL pointer passed to pdb_getsampwrid\n");#endif return nt_status; } /* now build the SAM_ACCOUNT */ if (!build_sam_account (smbpasswd_state, sam_acct, smb_pw)) return nt_status; /* build_sam_account might change the SID on us, if the name was for the guest account */ if (NT_STATUS_IS_OK(nt_status) && !sid_equal(pdb_get_user_sid(sam_acct), sid)) { fstring sid_string1, sid_string2; DEBUG(1, ("looking for user with sid %s instead returned %s for account %s!?!\n", sid_to_string(sid_string1, sid), sid_to_string(sid_string2, pdb_get_user_sid(sam_acct)), pdb_get_username(sam_acct))); return NT_STATUS_NO_SUCH_USER; } /* success */ return NT_STATUS_OK;}static NTSTATUS smbpasswd_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sampass){ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd smb_pw; /* convert the SAM_ACCOUNT */ if (!build_smb_pass(&smb_pw, sampass)) { return NT_STATUS_UNSUCCESSFUL; } /* add the entry */ if(!add_smbfilepwd_entry(smbpasswd_state, &smb_pw)) { return NT_STATUS_UNSUCCESSFUL; } return NT_STATUS_OK;}static NTSTATUS smbpasswd_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sampass){ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; struct smb_passwd smb_pw; /* convert the SAM_ACCOUNT */ if (!build_smb_pass(&smb_pw, sampass)) { DEBUG(0, ("smbpasswd_update_sam_account: build_smb_pass failed!\n")); return NT_STATUS_UNSUCCESSFUL; } /* update the entry */ if(!mod_smbfilepwd_entry(smbpasswd_state, &smb_pw)) { DEBUG(0, ("smbpasswd_update_sam_account: mod_smbfilepwd_entry failed!\n")); return NT_STATUS_UNSUCCESSFUL; } return NT_STATUS_OK;}static NTSTATUS smbpasswd_delete_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *sampass){ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data; const char *username = pdb_get_username(sampass); if (del_smbfilepwd_entry(smbpasswd_state, username)) return NT_STATUS_OK; return NT_STATUS_UNSUCCESSFUL;}static NTSTATUS smbpasswd_rename_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *old_acct, const char *newname){ pstring rename_script; SAM_ACCOUNT *new_acct = NULL; BOOL interim_account = False; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if (!*(lp_renameuser_script())) goto done; if (!pdb_copy_sam_account(old_acct, &new_acct) || !pdb_set_username(new_acct, newname, PDB_CHANGED)) goto done; ret = smbpasswd_add_sam_account(my_methods, new_acct); if (!NT_STATUS_IS_OK(ret)) goto done; interim_account = True; /* rename the posix user */ pstrcpy(rename_script, lp_renameuser_script()); if (*rename_script) { int rename_ret; pstring_sub(rename_script, "%unew", newname); pstring_sub(rename_script, "%uold", pdb_get_username(old_acct)); rename_ret = smbrun(rename_script, NULL); DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret)); if (rename_ret) goto done; } else { goto done; } smbpasswd_delete_sam_account(my_methods, old_acct); interim_account = False;done: /* cleanup */ if (interim_account) smbpasswd_delete_sam_account(my_methods, new_acct); if (new_acct) pdb_free_sam(&new_acct); return (ret); }static void free_private_data(void **vp) { struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp; endsmbfilepwent((*privates)->pw_file, &((*privates)->pw_file_lock_depth)); *privates = NULL; /* No need to free any further, as it is talloc()ed */}static NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location){ NTSTATUS nt_status; struct smbpasswd_privates *privates; if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { return nt_status; } (*pdb_method)->name = "smbpasswd"; (*pdb_method)->setsampwent = smbpasswd_setsampwent; (*pdb_method)->endsampwent = smbpasswd_endsampwent; (*pdb_method)->getsampwent = smbpasswd_getsampwent; (*pdb_method)->getsampwnam = smbpasswd_getsampwnam; (*pdb_method)->getsampwsid = smbpasswd_getsampwsid; (*pdb_method)->add_sam_account = smbpasswd_add_sam_account; (*pdb_method)->update_sam_account = smbpasswd_update_sam_account; (*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account; (*pdb_method)->rename_sam_account = smbpasswd_rename_sam_account; /* Setup private data and free function */ privates = TALLOC_ZERO_P(pdb_context->mem_ctx, struct smbpasswd_privates); if (!privates) { DEBUG(0, ("talloc() failed for smbpasswd private_data!\n")); return NT_STATUS_NO_MEMORY; } /* Store some config details */ if (location) { privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, location); } else { privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, lp_smb_passwd_file()); } if (!privates->smbpasswd_file) { DEBUG(0, ("talloc_strdp() failed for storing smbpasswd location!\n")); return NT_STATUS_NO_MEMORY; } (*pdb_method)->private_data = privates; (*pdb_method)->free_private_data = free_private_data; return NT_STATUS_OK;}NTSTATUS pdb_smbpasswd_init(void) { return smb_register_passdb(PASSDB_INTERFACE_VERSION, "smbpasswd", pdb_init_smbpasswd);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -