passdb/pdb_tdb.c

説明を見る。
00001 /*
00002  * Unix SMB/CIFS implementation. 
00003  * SMB parameters and setup
00004  * Copyright (C) Andrew Tridgell   1992-1998
00005  * Copyright (C) Simo Sorce        2000-2003
00006  * Copyright (C) Gerald Carter     2000-2006
00007  * Copyright (C) Jeremy Allison    2001
00008  * Copyright (C) Andrew Bartlett   2002
00009  * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
00010  * 
00011  * This program is free software; you can redistribute it and/or modify it under
00012  * the terms of the GNU General Public License as published by the Free
00013  * Software Foundation; either version 2 of the License, or (at your option)
00014  * any later version.
00015  * 
00016  * This program is distributed in the hope that it will be useful, but WITHOUT
00017  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00019  * more details.
00020  * 
00021  * You should have received a copy of the GNU General Public License along with
00022  * this program; if not, write to the Free Software Foundation, Inc., 675
00023  * Mass Ave, Cambridge, MA 02139, USA.
00024  */
00025 
00026 #include "includes.h"
00027 
00028 #if 0 /* when made a module use this */
00029 
00030 static int tdbsam_debug_level = DBGC_ALL;
00031 #undef DBGC_CLASS
00032 #define DBGC_CLASS tdbsam_debug_level
00033 
00034 #else
00035 
00036 #undef DBGC_CLASS
00037 #define DBGC_CLASS DBGC_PASSDB
00038 
00039 #endif
00040 
00041 #define TDBSAM_VERSION  3       /* Most recent TDBSAM version */
00042 #define TDBSAM_VERSION_STRING   "INFO/version"
00043 #define PASSDB_FILE_NAME        "passdb.tdb"
00044 #define USERPREFIX              "USER_"
00045 #define RIDPREFIX               "RID_"
00046 #define PRIVPREFIX              "PRIV_"
00047 
00048 struct pwent_list {
00049         struct pwent_list *prev, *next;
00050         TDB_DATA key;
00051 };
00052 static struct pwent_list *tdbsam_pwent_list;
00053 static BOOL pwent_initialized;
00054 
00055 /* GLOBAL TDB SAM CONTEXT */
00056 
00057 static TDB_CONTEXT *tdbsam;
00058 static int ref_count = 0;
00059 static pstring tdbsam_filename;
00060 
00061 /**********************************************************************
00062  Marshall/unmarshall struct samu structs.
00063  *********************************************************************/
00064 
00065 #define TDB_FORMAT_STRING_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
00066 #define TDB_FORMAT_STRING_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
00067 #define TDB_FORMAT_STRING_V2       "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
00068 
00069 /*********************************************************************
00070 *********************************************************************/
00071 
00072 static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
00073 {
00074 
00075         /* times are stored as 32bit integer
00076            take care on system with 64bit wide time_t
00077            --SSS */
00078         uint32  logon_time,
00079                 logoff_time,
00080                 kickoff_time,
00081                 pass_last_set_time,
00082                 pass_can_change_time,
00083                 pass_must_change_time;
00084         char *username = NULL;
00085         char *domain = NULL;
00086         char *nt_username = NULL;
00087         char *dir_drive = NULL;
00088         char *unknown_str = NULL;
00089         char *munged_dial = NULL;
00090         char *fullname = NULL;
00091         char *homedir = NULL;
00092         char *logon_script = NULL;
00093         char *profile_path = NULL;
00094         char *acct_desc = NULL;
00095         char *workstations = NULL;
00096         uint32  username_len, domain_len, nt_username_len,
00097                 dir_drive_len, unknown_str_len, munged_dial_len,
00098                 fullname_len, homedir_len, logon_script_len,
00099                 profile_path_len, acct_desc_len, workstations_len;
00100                 
00101         uint32  user_rid, group_rid, remove_me, hours_len, unknown_6;
00102         uint16  acct_ctrl, logon_divs;
00103         uint16  bad_password_count, logon_count;
00104         uint8   *hours = NULL;
00105         uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
00106         uint32          len = 0;
00107         uint32          lm_pw_len, nt_pw_len, hourslen;
00108         BOOL ret = True;
00109         
00110         if(sampass == NULL || buf == NULL) {
00111                 DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
00112                 return False;
00113         }
00114 
00115 /* TDB_FORMAT_STRING_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
00116 
00117         /* unpack the buffer into variables */
00118         len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V0,
00119                 &logon_time,                                            /* d */
00120                 &logoff_time,                                           /* d */
00121                 &kickoff_time,                                          /* d */
00122                 &pass_last_set_time,                                    /* d */
00123                 &pass_can_change_time,                                  /* d */
00124                 &pass_must_change_time,                                 /* d */
00125                 &username_len, &username,                               /* B */
00126                 &domain_len, &domain,                                   /* B */
00127                 &nt_username_len, &nt_username,                         /* B */
00128                 &fullname_len, &fullname,                               /* B */
00129                 &homedir_len, &homedir,                                 /* B */
00130                 &dir_drive_len, &dir_drive,                             /* B */
00131                 &logon_script_len, &logon_script,                       /* B */
00132                 &profile_path_len, &profile_path,                       /* B */
00133                 &acct_desc_len, &acct_desc,                             /* B */
00134                 &workstations_len, &workstations,                       /* B */
00135                 &unknown_str_len, &unknown_str,                         /* B */
00136                 &munged_dial_len, &munged_dial,                         /* B */
00137                 &user_rid,                                              /* d */
00138                 &group_rid,                                             /* d */
00139                 &lm_pw_len, &lm_pw_ptr,                                 /* B */
00140                 &nt_pw_len, &nt_pw_ptr,                                 /* B */
00141                 &acct_ctrl,                                             /* w */
00142                 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
00143                 &logon_divs,                                            /* w */
00144                 &hours_len,                                             /* d */
00145                 &hourslen, &hours,                                      /* B */
00146                 &bad_password_count,                                    /* w */
00147                 &logon_count,                                           /* w */
00148                 &unknown_6);                                            /* d */
00149                 
00150         if (len == (uint32) -1)  {
00151                 ret = False;
00152                 goto done;
00153         }
00154 
00155         pdb_set_logon_time(sampass, logon_time, PDB_SET);
00156         pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
00157         pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
00158         pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
00159         pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
00160         pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
00161 
00162         pdb_set_username(sampass, username, PDB_SET); 
00163         pdb_set_domain(sampass, domain, PDB_SET);
00164         pdb_set_nt_username(sampass, nt_username, PDB_SET);
00165         pdb_set_fullname(sampass, fullname, PDB_SET);
00166 
00167         if (homedir) {
00168                 pdb_set_homedir(sampass, homedir, PDB_SET);
00169         }
00170         else {
00171                 pdb_set_homedir(sampass, 
00172                         talloc_sub_basic(sampass, username, domain,
00173                                          lp_logon_home()),
00174                         PDB_DEFAULT);
00175         }
00176 
00177         if (dir_drive)  
00178                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
00179         else {
00180                 pdb_set_dir_drive(sampass, 
00181                         talloc_sub_basic(sampass, username, domain,
00182                                          lp_logon_drive()),
00183                         PDB_DEFAULT);
00184         }
00185 
00186         if (logon_script) 
00187                 pdb_set_logon_script(sampass, logon_script, PDB_SET);
00188         else {
00189                 pdb_set_logon_script(sampass, 
00190                         talloc_sub_basic(sampass, username, domain,
00191                                          lp_logon_script()),
00192                         PDB_DEFAULT);
00193         }
00194         
00195         if (profile_path) {     
00196                 pdb_set_profile_path(sampass, profile_path, PDB_SET);
00197         } else {
00198                 pdb_set_profile_path(sampass, 
00199                         talloc_sub_basic(sampass, username, domain,
00200                                          lp_logon_path()),
00201                         PDB_DEFAULT);
00202         }
00203 
00204         pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
00205         pdb_set_workstations(sampass, workstations, PDB_SET);
00206         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
00207 
00208         if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
00209                 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
00210                         ret = False;
00211                         goto done;
00212                 }
00213         }
00214 
00215         if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
00216                 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
00217                         ret = False;
00218                         goto done;
00219                 }
00220         }
00221 
00222         pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
00223         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
00224         pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
00225         pdb_set_hours_len(sampass, hours_len, PDB_SET);
00226         pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
00227         pdb_set_logon_count(sampass, logon_count, PDB_SET);
00228         pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
00229         pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
00230         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
00231         pdb_set_hours(sampass, hours, PDB_SET);
00232 
00233 done:
00234 
00235         SAFE_FREE(username);
00236         SAFE_FREE(domain);
00237         SAFE_FREE(nt_username);
00238         SAFE_FREE(fullname);
00239         SAFE_FREE(homedir);
00240         SAFE_FREE(dir_drive);
00241         SAFE_FREE(logon_script);
00242         SAFE_FREE(profile_path);
00243         SAFE_FREE(acct_desc);
00244         SAFE_FREE(workstations);
00245         SAFE_FREE(munged_dial);
00246         SAFE_FREE(unknown_str);
00247         SAFE_FREE(lm_pw_ptr);
00248         SAFE_FREE(nt_pw_ptr);
00249         SAFE_FREE(hours);
00250 
00251         return ret;
00252 }
00253 
00254 /*********************************************************************
00255 *********************************************************************/
00256 
00257 static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
00258 {
00259 
00260         /* times are stored as 32bit integer
00261            take care on system with 64bit wide time_t
00262            --SSS */
00263         uint32  logon_time,
00264                 logoff_time,
00265                 kickoff_time,
00266                 bad_password_time,
00267                 pass_last_set_time,
00268                 pass_can_change_time,
00269                 pass_must_change_time;
00270         char *username = NULL;
00271         char *domain = NULL;
00272         char *nt_username = NULL;
00273         char *dir_drive = NULL;
00274         char *unknown_str = NULL;
00275         char *munged_dial = NULL;
00276         char *fullname = NULL;
00277         char *homedir = NULL;
00278         char *logon_script = NULL;
00279         char *profile_path = NULL;
00280         char *acct_desc = NULL;
00281         char *workstations = NULL;
00282         uint32  username_len, domain_len, nt_username_len,
00283                 dir_drive_len, unknown_str_len, munged_dial_len,
00284                 fullname_len, homedir_len, logon_script_len,
00285                 profile_path_len, acct_desc_len, workstations_len;
00286                 
00287         uint32  user_rid, group_rid, remove_me, hours_len, unknown_6;
00288         uint16  acct_ctrl, logon_divs;
00289         uint16  bad_password_count, logon_count;
00290         uint8   *hours = NULL;
00291         uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
00292         uint32          len = 0;
00293         uint32          lm_pw_len, nt_pw_len, hourslen;
00294         BOOL ret = True;
00295         
00296         if(sampass == NULL || buf == NULL) {
00297                 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
00298                 return False;
00299         }
00300 
00301 /* TDB_FORMAT_STRING_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
00302 
00303         /* unpack the buffer into variables */
00304         len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
00305                 &logon_time,                                            /* d */
00306                 &logoff_time,                                           /* d */
00307                 &kickoff_time,                                          /* d */
00308                 /* Change from V0 is addition of bad_password_time field. */
00309                 &bad_password_time,                                     /* d */
00310                 &pass_last_set_time,                                    /* d */
00311                 &pass_can_change_time,                                  /* d */
00312                 &pass_must_change_time,                                 /* d */
00313                 &username_len, &username,                               /* B */
00314                 &domain_len, &domain,                                   /* B */
00315                 &nt_username_len, &nt_username,                         /* B */
00316                 &fullname_len, &fullname,                               /* B */
00317                 &homedir_len, &homedir,                                 /* B */
00318                 &dir_drive_len, &dir_drive,                             /* B */
00319                 &logon_script_len, &logon_script,                       /* B */
00320                 &profile_path_len, &profile_path,                       /* B */
00321                 &acct_desc_len, &acct_desc,                             /* B */
00322                 &workstations_len, &workstations,                       /* B */
00323                 &unknown_str_len, &unknown_str,                         /* B */
00324                 &munged_dial_len, &munged_dial,                         /* B */
00325                 &user_rid,                                              /* d */
00326                 &group_rid,                                             /* d */
00327                 &lm_pw_len, &lm_pw_ptr,                                 /* B */
00328                 &nt_pw_len, &nt_pw_ptr,                                 /* B */
00329                 &acct_ctrl,                                             /* w */
00330                 &remove_me,                                             /* d */
00331                 &logon_divs,                                            /* w */
00332                 &hours_len,                                             /* d */
00333                 &hourslen, &hours,                                      /* B */
00334                 &bad_password_count,                                    /* w */
00335                 &logon_count,                                           /* w */
00336                 &unknown_6);                                            /* d */
00337                 
00338         if (len == (uint32) -1)  {
00339                 ret = False;
00340                 goto done;
00341         }
00342 
00343         pdb_set_logon_time(sampass, logon_time, PDB_SET);
00344         pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
00345         pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
00346 
00347         /* Change from V0 is addition of bad_password_time field. */
00348         pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
00349         pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
00350         pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
00351         pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
00352 
00353         pdb_set_username(sampass, username, PDB_SET); 
00354         pdb_set_domain(sampass, domain, PDB_SET);
00355         pdb_set_nt_username(sampass, nt_username, PDB_SET);
00356         pdb_set_fullname(sampass, fullname, PDB_SET);
00357 
00358         if (homedir) {
00359                 pdb_set_homedir(sampass, homedir, PDB_SET);
00360         }
00361         else {
00362                 pdb_set_homedir(sampass, 
00363                         talloc_sub_basic(sampass, username, domain,
00364                                          lp_logon_home()),
00365                         PDB_DEFAULT);
00366         }
00367 
00368         if (dir_drive)  
00369                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
00370         else {
00371                 pdb_set_dir_drive(sampass, 
00372                         talloc_sub_basic(sampass, username, domain,
00373                                          lp_logon_drive()),
00374                         PDB_DEFAULT);
00375         }
00376 
00377         if (logon_script) 
00378                 pdb_set_logon_script(sampass, logon_script, PDB_SET);
00379         else {
00380                 pdb_set_logon_script(sampass, 
00381                         talloc_sub_basic(sampass, username, domain,
00382                                          lp_logon_script()),
00383                         PDB_DEFAULT);
00384         }
00385         
00386         if (profile_path) {     
00387                 pdb_set_profile_path(sampass, profile_path, PDB_SET);
00388         } else {
00389                 pdb_set_profile_path(sampass, 
00390                         talloc_sub_basic(sampass, username, domain,
00391                                          lp_logon_path()),
00392                         PDB_DEFAULT);
00393         }
00394 
00395         pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
00396         pdb_set_workstations(sampass, workstations, PDB_SET);
00397         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
00398 
00399         if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
00400                 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
00401                         ret = False;
00402                         goto done;
00403                 }
00404         }
00405 
00406         if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
00407                 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
00408                         ret = False;
00409                         goto done;
00410                 }
00411         }
00412 
00413         pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
00414 
00415         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
00416         pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
00417         pdb_set_hours_len(sampass, hours_len, PDB_SET);
00418         pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
00419         pdb_set_logon_count(sampass, logon_count, PDB_SET);
00420         pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
00421         pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
00422         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
00423         pdb_set_hours(sampass, hours, PDB_SET);
00424 
00425 done:
00426 
00427         SAFE_FREE(username);
00428         SAFE_FREE(domain);
00429         SAFE_FREE(nt_username);
00430         SAFE_FREE(fullname);
00431         SAFE_FREE(homedir);
00432         SAFE_FREE(dir_drive);
00433         SAFE_FREE(logon_script);
00434         SAFE_FREE(profile_path);
00435         SAFE_FREE(acct_desc);
00436         SAFE_FREE(workstations);
00437         SAFE_FREE(munged_dial);
00438         SAFE_FREE(unknown_str);
00439         SAFE_FREE(lm_pw_ptr);
00440         SAFE_FREE(nt_pw_ptr);
00441         SAFE_FREE(hours);
00442 
00443         return ret;
00444 }
00445 
00446 BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
00447 {
00448 
00449         /* times are stored as 32bit integer
00450            take care on system with 64bit wide time_t
00451            --SSS */
00452         uint32  logon_time,
00453                 logoff_time,
00454                 kickoff_time,
00455                 bad_password_time,
00456                 pass_last_set_time,
00457                 pass_can_change_time,
00458                 pass_must_change_time;
00459         char *username = NULL;
00460         char *domain = NULL;
00461         char *nt_username = NULL;
00462         char *dir_drive = NULL;
00463         char *unknown_str = NULL;
00464         char *munged_dial = NULL;
00465         char *fullname = NULL;
00466         char *homedir = NULL;
00467         char *logon_script = NULL;
00468         char *profile_path = NULL;
00469         char *acct_desc = NULL;
00470         char *workstations = NULL;
00471         uint32  username_len, domain_len, nt_username_len,
00472                 dir_drive_len, unknown_str_len, munged_dial_len,
00473                 fullname_len, homedir_len, logon_script_len,
00474                 profile_path_len, acct_desc_len, workstations_len;
00475                 
00476         uint32  user_rid, group_rid, hours_len, unknown_6;
00477         uint16  acct_ctrl, logon_divs;
00478         uint16  bad_password_count, logon_count;
00479         uint8   *hours = NULL;
00480         uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
00481         uint32          len = 0;
00482         uint32          lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
00483         uint32 pwHistLen = 0;
00484         BOOL ret = True;
00485         fstring tmpstring;
00486         BOOL expand_explicit = lp_passdb_expand_explicit();
00487         
00488         if(sampass == NULL || buf == NULL) {
00489                 DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
00490                 return False;
00491         }
00492                                                                         
00493 /* TDB_FORMAT_STRING_V2       "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
00494 
00495         /* unpack the buffer into variables */
00496         len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V2,
00497                 &logon_time,                                            /* d */
00498                 &logoff_time,                                           /* d */
00499                 &kickoff_time,                                          /* d */
00500                 &bad_password_time,                                     /* d */
00501                 &pass_last_set_time,                                    /* d */
00502                 &pass_can_change_time,                                  /* d */
00503                 &pass_must_change_time,                                 /* d */
00504                 &username_len, &username,                               /* B */
00505                 &domain_len, &domain,                                   /* B */
00506                 &nt_username_len, &nt_username,                         /* B */
00507                 &fullname_len, &fullname,                               /* B */
00508                 &homedir_len, &homedir,                                 /* B */
00509                 &dir_drive_len, &dir_drive,                             /* B */
00510                 &logon_script_len, &logon_script,                       /* B */
00511                 &profile_path_len, &profile_path,                       /* B */
00512                 &acct_desc_len, &acct_desc,                             /* B */
00513                 &workstations_len, &workstations,                       /* B */
00514                 &unknown_str_len, &unknown_str,                         /* B */
00515                 &munged_dial_len, &munged_dial,                         /* B */
00516                 &user_rid,                                              /* d */
00517                 &group_rid,                                             /* d */
00518                 &lm_pw_len, &lm_pw_ptr,                                 /* B */
00519                 &nt_pw_len, &nt_pw_ptr,                                 /* B */
00520                 /* Change from V1 is addition of password history field. */
00521                 &nt_pw_hist_len, &nt_pw_hist_ptr,                       /* B */
00522                 &acct_ctrl,                                             /* w */
00523                 /* Also "remove_me" field was removed. */
00524                 &logon_divs,                                            /* w */
00525                 &hours_len,                                             /* d */
00526                 &hourslen, &hours,                                      /* B */
00527                 &bad_password_count,                                    /* w */
00528                 &logon_count,                                           /* w */
00529                 &unknown_6);                                            /* d */
00530                 
00531         if (len == (uint32) -1)  {
00532                 ret = False;
00533                 goto done;
00534         }
00535 
00536         pdb_set_logon_time(sampass, logon_time, PDB_SET);
00537         pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
00538         pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
00539         pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
00540         pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
00541         pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
00542         pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
00543 
00544         pdb_set_username(sampass, username, PDB_SET); 
00545         pdb_set_domain(sampass, domain, PDB_SET);
00546         pdb_set_nt_username(sampass, nt_username, PDB_SET);
00547         pdb_set_fullname(sampass, fullname, PDB_SET);
00548 
00549         if (homedir) {
00550                 fstrcpy( tmpstring, homedir );
00551                 if (expand_explicit) {
00552                         standard_sub_basic( username, domain, tmpstring,
00553                                             sizeof(tmpstring) );
00554                 }
00555                 pdb_set_homedir(sampass, tmpstring, PDB_SET);
00556         }
00557         else {
00558                 pdb_set_homedir(sampass, 
00559                         talloc_sub_basic(sampass, username, domain,
00560                                          lp_logon_home()),
00561                         PDB_DEFAULT);
00562         }
00563 
00564         if (dir_drive)  
00565                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
00566         else
00567                 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
00568 
00569         if (logon_script) {
00570                 fstrcpy( tmpstring, logon_script );
00571                 if (expand_explicit) {
00572                         standard_sub_basic( username, domain, tmpstring,
00573                                             sizeof(tmpstring) );
00574                 }
00575                 pdb_set_logon_script(sampass, tmpstring, PDB_SET);
00576         }
00577         else {
00578                 pdb_set_logon_script(sampass, 
00579                         talloc_sub_basic(sampass, username, domain,
00580                                          lp_logon_script()),
00581                         PDB_DEFAULT);
00582         }
00583         
00584         if (profile_path) {     
00585                 fstrcpy( tmpstring, profile_path );
00586                 if (expand_explicit) {
00587                         standard_sub_basic( username, domain, tmpstring,
00588                                             sizeof(tmpstring) );
00589                 }
00590                 pdb_set_profile_path(sampass, tmpstring, PDB_SET);
00591         } 
00592         else {
00593                 pdb_set_profile_path(sampass, 
00594                         talloc_sub_basic(sampass, username, domain,
00595                                          lp_logon_path()),
00596                         PDB_DEFAULT);
00597         }
00598 
00599         pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
00600         pdb_set_workstations(sampass, workstations, PDB_SET);
00601         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
00602 
00603         if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
00604                 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
00605                         ret = False;
00606                         goto done;
00607                 }
00608         }
00609 
00610         if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
00611                 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
00612                         ret = False;
00613                         goto done;
00614                 }
00615         }
00616 
00617         /* Change from V1 is addition of password history field. */
00618         pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
00619         if (pwHistLen) {
00620                 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
00621                 if (!pw_hist) {
00622                         ret = False;
00623                         goto done;
00624                 }
00625                 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
00626                 if (nt_pw_hist_ptr && nt_pw_hist_len) {
00627                         int i;
00628                         SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
00629                         nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
00630                         for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
00631                                 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
00632                                         &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
00633                                         PW_HISTORY_ENTRY_LEN);
00634                         }
00635                 }
00636                 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
00637                         SAFE_FREE(pw_hist);
00638                         ret = False;
00639                         goto done;
00640                 }
00641                 SAFE_FREE(pw_hist);
00642         } else {
00643                 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
00644         }
00645 
00646         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
00647         pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
00648         pdb_set_hours_len(sampass, hours_len, PDB_SET);
00649         pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
00650         pdb_set_logon_count(sampass, logon_count, PDB_SET);
00651         pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
00652         pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
00653         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
00654         pdb_set_hours(sampass, hours, PDB_SET);
00655 
00656 done:
00657 
00658         SAFE_FREE(username);
00659         SAFE_FREE(domain);
00660         SAFE_FREE(nt_username);
00661         SAFE_FREE(fullname);
00662         SAFE_FREE(homedir);
00663         SAFE_FREE(dir_drive);
00664         SAFE_FREE(logon_script);
00665         SAFE_FREE(profile_path);
00666         SAFE_FREE(acct_desc);
00667         SAFE_FREE(workstations);
00668         SAFE_FREE(munged_dial);
00669         SAFE_FREE(unknown_str);
00670         SAFE_FREE(lm_pw_ptr);
00671         SAFE_FREE(nt_pw_ptr);
00672         SAFE_FREE(nt_pw_hist_ptr);
00673         SAFE_FREE(hours);
00674 
00675         return ret;
00676 }
00677 
00678 
00679 /**********************************************************************
00680  Intialize a struct samu struct from a BYTE buffer of size len
00681  *********************************************************************/
00682 
00683 static BOOL init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
00684 {
00685         return init_sam_from_buffer_v3(sampass, buf, buflen);
00686 }
00687 
00688 /**********************************************************************
00689  Intialize a BYTE buffer from a struct samu struct
00690  *********************************************************************/
00691 
00692 static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, BOOL size_only)
00693 {
00694         return init_buffer_from_sam_v3(buf, sampass, size_only);
00695 }
00696 
00697 /**********************************************************************
00698  Intialize a BYTE buffer from a struct samu struct
00699  *********************************************************************/
00700 
00701 static BOOL tdbsam_convert(int32 from) 
00702 {
00703         const char      *vstring = TDBSAM_VERSION_STRING;
00704         const char      *prefix = USERPREFIX;
00705         TDB_DATA        data, key, old_key;
00706         uint8           *buf = NULL;
00707         BOOL            ret;
00708 
00709         /* handle a Samba upgrade */
00710         tdb_lock_bystring(tdbsam, vstring);
00711         
00712         /* Enumerate all records and convert them */
00713         key = tdb_firstkey(tdbsam);
00714 
00715         while (key.dptr) {
00716         
00717                 /* skip all non-USER entries (eg. RIDs) */
00718                 while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
00719                         old_key = key;
00720                         /* increment to next in line */
00721                         key = tdb_nextkey(tdbsam, key);
00722                         SAFE_FREE(old_key.dptr);
00723                 }
00724         
00725                 if (key.dptr) {
00726                         struct samu *user = NULL;
00727 
00728                         /* read from tdbsam */
00729                         data = tdb_fetch(tdbsam, key);
00730                         if (!data.dptr) {
00731                                 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
00732                                 return False;
00733                         }
00734         
00735                         /* unpack the buffer from the former format */
00736                         if ( !(user = samu_new( NULL )) ) {
00737                                 DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
00738                                 SAFE_FREE( data.dptr );
00739                                 return False;
00740                         }
00741                         DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
00742                         switch (from) {
00743                                 case 0:
00744                                         ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
00745                                         break;
00746                                 case 1:
00747                                         ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
00748                                         break;
00749                                 case 2:
00750                                         ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
00751                                         break;
00752                                 case 3:
00753                                         ret = init_sam_from_buffer_v3(user, (uint8 *)data.dptr, data.dsize);
00754                                         break;
00755                                 default:
00756                                         /* unknown tdbsam version */
00757                                         ret = False;
00758                         }
00759                         if (!ret) {
00760                                 DEBUG(0,("tdbsam_convert: Bad struct samu entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
00761                                 SAFE_FREE(data.dptr);
00762                                 TALLOC_FREE(user );
00763                                 return False;
00764                         }
00765         
00766                         /* We're finished with the old data. */
00767                         SAFE_FREE(data.dptr);
00768 
00769                         /* pack from the buffer into the new format */
00770                         
00771                         DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
00772                         data.dsize = init_buffer_from_sam (&buf, user, False);
00773                         TALLOC_FREE(user );
00774                         
00775                         if ( data.dsize == -1 ) {
00776                                 DEBUG(0,("tdbsam_convert: cannot pack the struct samu into the new format\n"));
00777                                 return False;
00778                         }
00779                         data.dptr = (char *)buf;
00780                         
00781                         /* Store the buffer inside the TDBSAM */
00782                         if (tdb_store(tdbsam, key, data, TDB_MODIFY) != TDB_SUCCESS) {
00783                                 DEBUG(0,("tdbsam_convert: cannot store the struct samu (key:%s) in new format\n",key.dptr));
00784                                 SAFE_FREE(data.dptr);
00785                                 return False;
00786                         }
00787                         
00788                         SAFE_FREE(data.dptr);
00789                         
00790                         /* increment to next in line */
00791                         old_key = key;
00792                         key = tdb_nextkey(tdbsam, key);
00793                         SAFE_FREE(old_key.dptr);
00794                 }
00795                 
00796         }
00797 
00798         
00799         /* upgrade finished */
00800         tdb_store_int32(tdbsam, vstring, TDBSAM_VERSION);
00801         tdb_unlock_bystring(tdbsam, vstring);
00802 
00803         return(True);   
00804 }
00805 
00806 /*********************************************************************
00807  Open the tdbsam file based on the absolute path specified.
00808  Uses a reference count to allow multiple open calls.
00809 *********************************************************************/
00810 
00811 static BOOL tdbsam_open( const char *name )
00812 {
00813         int32   version;
00814         
00815         /* check if we are already open */
00816         
00817         if ( tdbsam ) {
00818                 ref_count++;
00819                 DEBUG(8,("tdbsam_open: Incrementing open reference count.  Ref count is now %d\n", 
00820                         ref_count));
00821                 return True;
00822         }
00823         
00824         SMB_ASSERT( ref_count == 0 );
00825         
00826         /* Try to open tdb passwd.  Create a new one if necessary */
00827         
00828         if (!(tdbsam = tdb_open_log(name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600))) {
00829                 DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd [%s]\n", name));
00830                 return False;
00831         }
00832 
00833         /* set the initial reference count - must be done before tdbsam_convert
00834            as that calls tdbsam_open()/tdbsam_close(). */
00835 
00836         ref_count = 1;
00837 
00838         /* Check the version */
00839         version = tdb_fetch_int32( tdbsam, TDBSAM_VERSION_STRING );
00840         
00841         if (version == -1) {
00842                 version = 0;    /* Version not found, assume version 0 */
00843         }
00844         
00845         /* Compare the version */
00846         if (version > TDBSAM_VERSION) {
00847                 /* Version more recent than the latest known */ 
00848                 DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
00849                 tdb_close( tdbsam );
00850                 ref_count = 0;
00851                 return False;
00852         } 
00853         
00854         
00855         if ( version < TDBSAM_VERSION ) {       
00856                 DEBUG(1, ("tdbsam_open: Converting version %d database to version %d.\n", 
00857                         version, TDBSAM_VERSION));
00858                 
00859                 if ( !tdbsam_convert(version) ) {
00860                         DEBUG(0, ("tdbsam_open: Error when trying to convert tdbsam [%s]\n",name));
00861                         tdb_close(tdbsam);
00862                         ref_count = 0;
00863                         return False;
00864                 }
00865                         
00866                 DEBUG(3, ("TDBSAM converted successfully.\n"));
00867         }
00868         
00869         DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));      
00870         
00871         return True;
00872 }
00873 
00874 /****************************************************************************
00875  wrapper atound tdb_close() to handle the reference count
00876 ****************************************************************************/
00877 
00878 void tdbsam_close( void )
00879 {
00880         ref_count--;
00881         
00882         DEBUG(8,("tdbsam_close: Reference count is now %d.\n", ref_count));
00883 
00884         SMB_ASSERT(ref_count >= 0 );
00885         
00886         if ( ref_count == 0 ) {
00887                 tdb_close( tdbsam );
00888                 tdbsam = NULL;
00889         }
00890         
00891         return;
00892 }
00893 
00894 /****************************************************************************
00895  creates a list of user keys
00896 ****************************************************************************/
00897 
00898 static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
00899 {
00900         const char *prefix = USERPREFIX;
00901         int  prefixlen = strlen (prefix);
00902         struct pwent_list *ptr;
00903         
00904         if ( strncmp(key.dptr, prefix, prefixlen) == 0 ) {
00905                 if ( !(ptr=SMB_MALLOC_P(struct pwent_list)) ) {
00906                         DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
00907                         
00908                         /* just return 0 and let the traversal continue */
00909                         return 0;
00910                 }
00911                 ZERO_STRUCTP(ptr);
00912                 
00913                 /* save a copy of the key */
00914                 
00915                 ptr->key.dptr = (char *)memdup( key.dptr, key.dsize );
00916                 if (!ptr->key.dptr) {
00917                         DEBUG(0,("tdbsam_traverse_setpwent: memdup failed\n"));
00918                         /* just return 0 and let the traversal continue */
00919                         SAFE_FREE(ptr);
00920                         return 0;
00921                 }
00922 
00923                 ptr->key.dsize = key.dsize;
00924                 
00925                 DLIST_ADD( tdbsam_pwent_list, ptr );
00926         
00927         }
00928         
00929         return 0;
00930 }
00931 
00932 /***************************************************************
00933  Open the TDB passwd database for SAM account enumeration.
00934  Save a list of user keys for iteration.
00935 ****************************************************************/
00936 
00937 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
00938 {
00939         if ( !tdbsam_open( tdbsam_filename ) ) {
00940                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
00941                 return NT_STATUS_ACCESS_DENIED;
00942         }
00943 
00944         tdb_traverse( tdbsam, tdbsam_traverse_setpwent, NULL );
00945         pwent_initialized = True;
00946 
00947         return NT_STATUS_OK;
00948 }
00949 
00950 
00951 /***************************************************************
00952  End enumeration of the TDB passwd list.
00953 ****************************************************************/
00954 
00955 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
00956 {
00957         struct pwent_list *ptr, *ptr_next;
00958         
00959         /* close the tdb only if we have a valid pwent state */
00960         
00961         if ( pwent_initialized ) {
00962                 DEBUG(7, ("endtdbpwent: closed sam database.\n"));
00963                 tdbsam_close();
00964         }
00965         
00966         /* clear out any remaining entries in the list */
00967         
00968         for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
00969                 ptr_next = ptr->next;
00970                 DLIST_REMOVE( tdbsam_pwent_list, ptr );
00971                 SAFE_FREE( ptr->key.dptr);
00972                 SAFE_FREE( ptr );
00973         }       
00974         
00975         pwent_initialized = False;
00976 }
00977 
00978 /*****************************************************************
00979  Get one struct samu from the TDB (next in line)
00980 *****************************************************************/
00981 
00982 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, struct samu *user)
00983 {
00984         NTSTATUS                nt_status = NT_STATUS_UNSUCCESSFUL;
00985         TDB_DATA                data;
00986         struct pwent_list       *pkey;
00987 
00988         if ( !user ) {
00989                 DEBUG(0,("tdbsam_getsampwent: struct samu is NULL.\n"));
00990                 return nt_status;
00991         }
00992 
00993         if ( !tdbsam_pwent_list ) {
00994                 DEBUG(4,("tdbsam_getsampwent: end of list\n"));
00995                 return nt_status;
00996         }
00997         
00998         /* pull the next entry */
00999                 
01000         pkey = tdbsam_pwent_list;
01001         DLIST_REMOVE( tdbsam_pwent_list, pkey );
01002         
01003         data = tdb_fetch(tdbsam, pkey->key);
01004 
01005         SAFE_FREE( pkey->key.dptr);
01006         SAFE_FREE( pkey);
01007         
01008         if ( !data.dptr ) {
01009                 DEBUG(5,("pdb_getsampwent: database entry not found.  Was the user deleted?\n"));
01010                 return nt_status;
01011         }
01012   
01013         if ( !init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize) ) {
01014                 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
01015         }
01016         
01017         SAFE_FREE( data.dptr );
01018 
01019         return NT_STATUS_OK;
01020 }
01021 
01022 /******************************************************************
01023  Lookup a name in the SAM TDB
01024 ******************************************************************/
01025 
01026 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, struct samu *user, const char *sname)
01027 {
01028         TDB_DATA        data, key;
01029         fstring         keystr;
01030         fstring         name;
01031 
01032         if ( !user ) {
01033                 DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
01034                 return NT_STATUS_NO_MEMORY;
01035         }
01036 
01037         /* Data is stored in all lower-case */
01038         fstrcpy(name, sname);
01039         strlower_m(name);
01040 
01041         /* set search key */
01042         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
01043         key.dptr = keystr;
01044         key.dsize = strlen(keystr) + 1;
01045 
01046         /* open the database */
01047                 
01048         if ( !tdbsam_open( tdbsam_filename ) ) {
01049                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
01050                 return NT_STATUS_ACCESS_DENIED;
01051         }
01052         
01053         /* get the record */
01054         
01055         data = tdb_fetch(tdbsam, key);
01056         if (!data.dptr) {
01057                 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
01058                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
01059                 DEBUGADD(5, (" Key: %s\n", keystr));
01060                 tdbsam_close();
01061                 return NT_STATUS_NO_SUCH_USER;
01062         }
01063   
01064         /* unpack the buffer */
01065         
01066         if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
01067                 DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
01068                 SAFE_FREE(data.dptr);
01069                 tdbsam_close();
01070                 return NT_STATUS_NO_MEMORY;
01071         }
01072         
01073         /* success */
01074         
01075         SAFE_FREE(data.dptr);
01076         tdbsam_close();
01077         
01078         return NT_STATUS_OK;
01079 }
01080 
01081 /***************************************************************************
01082  Search by rid
01083  **************************************************************************/
01084 
01085 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, struct samu *user, uint32 rid)
01086 {
01087         NTSTATUS                nt_status = NT_STATUS_UNSUCCESSFUL;
01088         TDB_DATA                data, key;
01089         fstring                 keystr;
01090         fstring                 name;
01091 
01092         if ( !user ) {
01093                 DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
01094                 return nt_status;
01095         }
01096         
01097         /* set search key */
01098         
01099         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
01100         key.dptr = keystr;
01101         key.dsize = strlen (keystr) + 1;
01102 
01103         /* open the database */
01104                 
01105         if ( !tdbsam_open( tdbsam_filename ) ) {
01106                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
01107                 return NT_STATUS_ACCESS_DENIED;
01108         }
01109 
01110         /* get the record */
01111         
01112         data = tdb_fetch (tdbsam, key);
01113         if (!data.dptr) {
01114                 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
01115                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
01116                 nt_status = NT_STATUS_UNSUCCESSFUL;
01117                 goto done;
01118         }
01119 
01120         fstrcpy(name, data.dptr);
01121         SAFE_FREE(data.dptr);
01122         
01123         nt_status = tdbsam_getsampwnam (my_methods, user, name);
01124 
01125  done:
01126         /* cleanup */
01127         
01128         tdbsam_close();
01129                 
01130         return nt_status;
01131 }
01132 
01133 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
01134 {
01135         uint32 rid;
01136         
01137         if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
01138                 return NT_STATUS_UNSUCCESSFUL;
01139 
01140         return tdbsam_getsampwrid(my_methods, user, rid);
01141 }
01142 
01143 static BOOL tdb_delete_samacct_only( struct samu *sam_pass )
01144 {
01145         TDB_DATA        key;
01146         fstring         keystr;
01147         fstring         name;
01148 
01149         fstrcpy(name, pdb_get_username(sam_pass));
01150         strlower_m(name);
01151         
01152         /* set the search key */
01153         
01154         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
01155         key.dptr = keystr;
01156         key.dsize = strlen (keystr) + 1;
01157         
01158         /* it's outaa here!  8^) */
01159         
01160         if (tdb_delete(tdbsam, key) != TDB_SUCCESS) {
01161                 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
01162                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
01163                 return False;
01164         }
01165         
01166         return True;
01167 }
01168 
01169 /***************************************************************************
01170  Delete a struct samu records for the username and RID key
01171 ****************************************************************************/
01172 
01173 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass)
01174 {
01175         NTSTATUS        nt_status = NT_STATUS_UNSUCCESSFUL;
01176         TDB_DATA        key;
01177         fstring         keystr;
01178         uint32          rid;
01179         fstring         name;
01180         
01181         /* open the database */
01182                 
01183         if ( !tdbsam_open( tdbsam_filename ) ) {
01184                 DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
01185                          tdbsam_filename));
01186                 return NT_STATUS_ACCESS_DENIED;
01187         }
01188 
01189         fstrcpy(name, pdb_get_username(sam_pass));
01190         strlower_m(name);
01191         
01192         /* set the search key */
01193 
01194         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
01195         key.dptr = keystr;
01196         key.dsize = strlen (keystr) + 1;
01197         
01198         rid = pdb_get_user_rid(sam_pass);
01199 
01200         /* it's outaa here!  8^) */
01201 
01202         if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
01203                 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
01204                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
01205                 nt_status = NT_STATUS_UNSUCCESSFUL;
01206                 goto done;
01207         }
01208 
01209         /* set the search key */
01210         
01211         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
01212         key.dptr = keystr;
01213         key.dsize = strlen (keystr) + 1;
01214 
01215         /* it's outaa here!  8^) */
01216         
01217         if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
01218                 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
01219                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
01220                 nt_status = NT_STATUS_UNSUCCESSFUL;
01221                 goto done;
01222         }
01223 
01224         nt_status = NT_STATUS_OK;
01225         
01226  done:
01227         tdbsam_close();
01228         
01229         return nt_status;
01230 }
01231 
01232 
01233 /***************************************************************************
01234  Update the TDB SAM account record only
01235  Assumes that the tdbsam is already open 
01236 ****************************************************************************/
01237 static BOOL tdb_update_samacct_only( struct samu* newpwd, int flag )
01238 {
01239         TDB_DATA        key, data;
01240         uint8           *buf = NULL;
01241         fstring         keystr;
01242         fstring         name;
01243         BOOL            ret = True;
01244 
01245         /* copy the struct samu struct into a BYTE buffer for storage */
01246         
01247         if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
01248                 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
01249                 ret = False;
01250                 goto done;
01251         }
01252         data.dptr = (char *)buf;
01253 
01254         fstrcpy(name, pdb_get_username(newpwd));
01255         strlower_m(name);
01256         
01257         DEBUG(5, ("Storing %saccount %s with RID %d\n", 
01258                   flag == TDB_INSERT ? "(new) " : "", name, 
01259                   pdb_get_user_rid(newpwd)));
01260 
01261         /* setup the USER index key */
01262         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
01263         key.dptr = keystr;
01264         key.dsize = strlen(keystr) + 1;
01265 
01266         /* add the account */
01267         
01268         if ( tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS ) {
01269                 DEBUG(0, ("Unable to modify passwd TDB!"));
01270                 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam)));
01271                 DEBUGADD(0, (" occured while storing the main record (%s)\n",
01272                              keystr));
01273                 ret = False;
01274                 goto done;
01275         }
01276 
01277 done:   
01278         /* cleanup */
01279         SAFE_FREE(buf);
01280         
01281         return ret;
01282 }
01283 
01284 /***************************************************************************
01285  Update the TDB SAM RID record only
01286  Assumes that the tdbsam is already open 
01287 ****************************************************************************/
01288 static BOOL tdb_update_ridrec_only( struct samu* newpwd, int flag )
01289 {
01290         TDB_DATA        key, data;
01291         fstring         keystr;
01292         fstring         name;
01293 
01294         fstrcpy(name, pdb_get_username(newpwd));
01295         strlower_m(name);
01296 
01297         /* setup RID data */
01298         data.dsize = strlen(name) + 1;
01299         data.dptr = name;
01300 
01301         /* setup the RID index key */
01302         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,  pdb_get_user_rid(newpwd));
01303         key.dptr = keystr;
01304         key.dsize = strlen (keystr) + 1;
01305         
01306         /* add the reference */
01307         if (tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS) {
01308                 DEBUG(0, ("Unable to modify TDB passwd !"));
01309                 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(tdbsam)));
01310                 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
01311                 return False;
01312         }
01313 
01314         return True;
01315 
01316 }
01317 
01318 /***************************************************************************
01319  Update the TDB SAM
01320 ****************************************************************************/
01321 
01322 static BOOL tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd, int flag)
01323 {
01324         BOOL            result = True;
01325 
01326         /* invalidate the existing TDB iterator if it is open */
01327         
01328         tdbsam_endsampwent( my_methods );
01329         
01330 #if 0 
01331         if ( !pdb_get_group_rid(newpwd) ) {
01332                 DEBUG (0,("tdb_update_sam: Failing to store a struct samu for [%s] "
01333                         "without a primary group RID\n", pdb_get_username(newpwd)));
01334                 return False;
01335         }
01336 #endif
01337 
01338         if (!pdb_get_user_rid(newpwd)) {
01339                 DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n", pdb_get_username(newpwd)));
01340                 return False;
01341         }
01342 
01343         /* open the database */
01344                 
01345         if ( !tdbsam_open( tdbsam_filename ) ) {
01346                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
01347                 return False;
01348         }
01349         
01350         if ( !tdb_update_samacct_only(newpwd, flag) || !tdb_update_ridrec_only(newpwd, flag)) {
01351                 result = False;
01352         }
01353 
01354         /* cleanup */
01355 
01356         tdbsam_close();
01357         
01358         return result;  
01359 }
01360 
01361 /***************************************************************************
01362  Modifies an existing struct samu
01363 ****************************************************************************/
01364 
01365 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
01366 {
01367         if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
01368                 return NT_STATUS_UNSUCCESSFUL;
01369         
01370         return NT_STATUS_OK;
01371 }
01372 
01373 /***************************************************************************
01374  Adds an existing struct samu
01375 ****************************************************************************/
01376 
01377 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
01378 {
01379         if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
01380                 return NT_STATUS_UNSUCCESSFUL;
01381                 
01382         return NT_STATUS_OK;
01383 }
01384 
01385 /***************************************************************************
01386  Renames a struct samu
01387  - check for the posix user/rename user script
01388  - Add and lock the new user record
01389  - rename the posix user
01390  - rewrite the rid->username record
01391  - delete the old user
01392  - unlock the new user record
01393 ***************************************************************************/
01394 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
01395                                           struct samu *old_acct, 
01396                                           const char *newname)
01397 {
01398         struct samu      *new_acct = NULL;
01399         pstring          rename_script;
01400         BOOL             interim_account = False;
01401         int              rename_ret;
01402         fstring          oldname_lower;
01403         fstring          newname_lower;
01404 
01405         /* can't do anything without an external script */
01406         
01407         pstrcpy(rename_script, lp_renameuser_script() );
01408         if ( ! *rename_script ) {
01409                 return NT_STATUS_ACCESS_DENIED;
01410         }
01411 
01412         /* invalidate the existing TDB iterator if it is open */
01413         
01414         tdbsam_endsampwent( my_methods );
01415 
01416         if ( !(new_acct = samu_new( NULL )) ) {
01417                 return NT_STATUS_NO_MEMORY;
01418         }
01419         
01420         if ( !pdb_copy_sam_account(new_acct, old_acct) 
01421                 || !pdb_set_username(new_acct, newname, PDB_CHANGED)) 
01422         {
01423                 TALLOC_FREE(new_acct );
01424                 return NT_STATUS_NO_MEMORY;
01425         }
01426 
01427         /* open the database */
01428                 
01429         if ( !tdbsam_open( tdbsam_filename ) ) {
01430                 DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
01431                 TALLOC_FREE(new_acct );
01432                 return NT_STATUS_ACCESS_DENIED;
01433         }
01434 
01435         /* add the new account and lock it */
01436         
01437         if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
01438                 goto done;
01439         }
01440         
01441         interim_account = True;
01442 
01443         if ( tdb_lock_bystring_with_timeout(tdbsam, newname, 30) == -1 ) {
01444                 goto done;
01445         }
01446 
01447         /* Rename the posix user.  Follow the semantics of _samr_create_user()
01448            so that we lower case the posix name but preserve the case in passdb */
01449 
01450         fstrcpy( oldname_lower, pdb_get_username(old_acct) );
01451         strlower_m( oldname_lower );
01452 
01453         fstrcpy( newname_lower, newname );
01454         strlower_m( newname_lower );
01455 
01456         string_sub2(rename_script, "%unew", newname_lower, sizeof(pstring), 
01457                 True, False, True);
01458         string_sub2(rename_script, "%uold", oldname_lower, sizeof(pstring), 
01459                 True, False, True);
01460         rename_ret = smbrun(rename_script, NULL);
01461 
01462         DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
01463 
01464         if (rename_ret == 0) {
01465                 smb_nscd_flush_user_cache();
01466         }
01467 
01468         if (rename_ret) {
01469                 goto done; 
01470         }
01471 
01472         /* rewrite the rid->username record */
01473         
01474         if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
01475                 goto done;
01476         }
01477         interim_account = False;
01478         tdb_unlock_bystring( tdbsam, newname );
01479 
01480         tdb_delete_samacct_only( old_acct );
01481         
01482         tdbsam_close();
01483         
01484         TALLOC_FREE(new_acct );
01485         return NT_STATUS_OK;
01486 
01487 done:   
01488         /* cleanup */
01489         if (interim_account) {
01490                 tdb_unlock_bystring(tdbsam, newname);
01491                 tdb_delete_samacct_only(new_acct);
01492         }
01493         
01494         tdbsam_close();
01495         
01496         if (new_acct)
01497                 TALLOC_FREE(new_acct);
01498         
01499         return NT_STATUS_ACCESS_DENIED; 
01500 }
01501 
01502 static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
01503 {
01504         return False;
01505 }
01506 
01507 /*
01508  * Historically, winbind was responsible for allocating RIDs, so the next RID
01509  * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
01510  * but for compatibility reasons we still keep the the next RID counter in
01511  * winbindd_idmap.tdb.
01512  */
01513 
01514 /*****************************************************************************
01515  Initialise idmap database. For now (Dec 2005) this is a copy of the code in
01516  sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
01517  winbind completely and store the RID counter in passdb.tdb.
01518 
01519  Dont' fully initialize with the HWM values, if it's new, we're only
01520  interested in the RID counter.
01521 *****************************************************************************/
01522 
01523 static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
01524 {
01525         int32 version;
01526 
01527         if (tdb_lock_bystring(tdb, "IDMAP_VERSION") != 0) {
01528                 DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
01529                 return False;
01530         }
01531 
01532         version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
01533 
01534         if (version == -1) {
01535                 /* No key found, must be a new db */
01536                 if (tdb_store_int32(tdb, "IDMAP_VERSION",
01537                                     IDMAP_VERSION) != 0) {
01538                         DEBUG(0, ("Could not store IDMAP_VERSION\n"));
01539                         tdb_unlock_bystring(tdb, "IDMAP_VERSION");
01540                         return False;
01541                 }
01542                 version = IDMAP_VERSION;
01543         }
01544 
01545         if (version != IDMAP_VERSION) {
01546                 DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
01547                           "start winbind once\n", IDMAP_VERSION, version));
01548                 tdb_unlock_bystring(tdb, "IDMAP_VERSION");
01549                 return False;
01550         }
01551 
01552         tdb_unlock_bystring(tdb, "IDMAP_VERSION");
01553         return True;
01554 }
01555 
01556 static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
01557 {
01558         TDB_CONTEXT *tdb;
01559         uint32 rid;
01560         BOOL ret = False;
01561 
01562         tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
01563                            TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
01564 
01565         if (tdb == NULL) {
01566                 DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
01567                 goto done;
01568         }
01569 
01570         if (!init_idmap_tdb(tdb)) {
01571                 DEBUG(1, ("Could not init idmap\n"));
01572                 goto done;
01573         }
01574 
01575         rid = BASE_RID;         /* Default if not set */
01576 
01577         if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
01578                 DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
01579                 goto done;
01580         }
01581 
01582         *prid = rid;
01583         ret = True;
01584 
01585  done:
01586         if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
01587                 smb_panic("tdb_close(idmap_tdb) failed\n");
01588         }
01589 
01590         return ret;
01591 }
01592 
01593 /*********************************************************************
01594  Initialize the tdb sam backend.  Setup the dispath table of methods,
01595  open the tdb, etc...
01596 *********************************************************************/
01597 
01598 static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
01599 {
01600         NTSTATUS nt_status;
01601         pstring tdbfile;
01602         const char *pfile = location;
01603 
01604         if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
01605                 return nt_status;
01606         }
01607 
01608         (*pdb_method)->name = "tdbsam";
01609 
01610         (*pdb_method)->setsampwent = tdbsam_setsampwent;
01611         (*pdb_method)->endsampwent = tdbsam_endsampwent;
01612         (*pdb_method)->getsampwent = tdbsam_getsampwent;
01613         (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
01614         (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
01615         (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
01616         (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
01617         (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
01618         (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
01619 
01620         (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
01621         (*pdb_method)->new_rid = tdbsam_new_rid;
01622 
01623         /* save the path for later */
01624                            
01625         if ( !location ) {
01626                 pstr_sprintf( tdbfile, "%s/%s", lp_private_dir(), PASSDB_FILE_NAME );
01627                 pfile = tdbfile;
01628         }
01629         pstrcpy( tdbsam_filename, pfile );
01630 
01631         /* no private data */
01632         
01633         (*pdb_method)->private_data      = NULL;
01634         (*pdb_method)->free_private_data = NULL;
01635 
01636         return NT_STATUS_OK;
01637 }
01638 
01639 NTSTATUS pdb_tdbsam_init(void)
01640 {
01641         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);
01642 }

Sambaに対してSat Aug 29 21:23:13 2009に生成されました。  doxygen 1.4.7