2 * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
3 * Copyright (C) Andrew Tridgell 1992-1998
4 * Copyright (C) Simo Sorce 2000
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 675
18 * Mass Ave, Cambridge, MA 02139, USA.
25 #define TDB_FORMAT_STRING "ddddddfffPPfPPPPffddBBwdwdBdd"
26 #define USERPREFIX "USER_"
28 extern int DEBUGLEVEL
;
29 extern pstring samlogon_user
;
30 extern BOOL sam_logon_in_ssb
;
35 TDB_CONTEXT
*passwd_tdb
;
39 static struct tdb_enum_info global_tdb_ent
;
40 static SAM_ACCOUNT global_sam_pass
;
42 /**********************************************************************
43 Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len
44 *********************************************************************/
45 static BOOL
init_sam_from_buffer (SAM_ACCOUNT
*sampass
, BYTE
*buf
,
48 static fstring username
,
54 static pstring full_name
,
60 static BYTE
*lm_pw_ptr
,
65 uint32 lmpwlen
, ntpwlen
, hourslen
;
67 /* unpack the buffer into variables */
68 len
= tdb_unpack (buf
, buflen
, TDB_FORMAT_STRING
,
70 &sampass
->logoff_time
,
71 &sampass
->kickoff_time
,
72 &sampass
->pass_last_set_time
,
73 &sampass
->pass_can_change_time
,
74 &sampass
->pass_must_change_time
,
95 &hourslen
, &sampass
->hours
,
103 * We have to copy the password hashes into static memory
104 * and free the memory allocated by tdb_unpack. This is because
105 * the sampass->own_memory flag is for all pointer members.
106 * The remaining members are using static memory and so
107 * the password hashes must as well. --jerry
111 memcpy(lm_pw
, lm_pw_ptr
, 16);
116 memcpy(nt_pw
, nt_pw_ptr
, 16);
120 /* using static memory for strings */
121 pdb_set_mem_ownership(sampass
, False
);
123 pdb_set_username (sampass
, username
);
124 pdb_set_domain (sampass
, domain
);
125 pdb_set_nt_username (sampass
, nt_username
);
126 pdb_set_fullname (sampass
, full_name
);
127 pdb_set_homedir (sampass
, home_dir
);
128 pdb_set_dir_drive (sampass
, dir_drive
);
129 pdb_set_logon_script (sampass
, logon_script
);
130 pdb_set_profile_path (sampass
, profile_path
);
131 pdb_set_acct_desc (sampass
, acct_desc
);
132 pdb_set_workstations (sampass
, workstations
);
133 pdb_set_munged_dial (sampass
, munged_dial
);
134 pdb_set_lanman_passwd(sampass
, lm_pw
);
135 pdb_set_nt_passwd (sampass
, nt_pw
);
140 /**********************************************************************
141 Intialize a BYTE buffer from a SAM_ACCOUNT struct
142 *********************************************************************/
143 static uint32
init_buffer_from_sam (BYTE
**buf
, SAM_ACCOUNT
*sampass
)
161 char null_pw
[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
163 /* do we have a valid SAM_ACCOUNT pointer? */
170 fstrcpy(username
, sampass
->username
);
171 fstrcpy(domain
, sampass
->domain
);
172 fstrcpy(nt_username
, sampass
->nt_username
);
173 fstrcpy(dir_drive
, sampass
->dir_drive
);
174 fstrcpy(unknown_str
, sampass
->unknown_str
);
175 fstrcpy(munged_dial
, sampass
->munged_dial
);
177 pstrcpy(full_name
, sampass
->full_name
);
178 pstrcpy(home_dir
, sampass
->home_dir
);
179 pstrcpy(logon_script
, sampass
->logon_script
);
180 pstrcpy(profile_path
, sampass
->profile_path
);
181 pstrcpy(acct_desc
, sampass
->acct_desc
);
182 pstrcpy(workstations
, sampass
->workstations
);
185 memcpy(lm_pw
, sampass
->lm_pw
, 16);
187 pdb_gethexpwd (null_pw
, lm_pw
);
190 memcpy(nt_pw
, sampass
->nt_pw
, 16);
192 pdb_gethexpwd (null_pw
, nt_pw
);
195 /* one time to get the size needed */
196 len
= tdb_pack(NULL
, 0, TDB_FORMAT_STRING
,
198 sampass
->logoff_time
,
199 sampass
->kickoff_time
,
200 sampass
->pass_last_set_time
,
201 sampass
->pass_can_change_time
,
202 sampass
->pass_must_change_time
,
223 MAX_HOURS_LEN
, sampass
->hours
,
228 /* malloc the space needed */
229 if ( (*buf
=(BYTE
*)malloc(len
)) == NULL
)
231 DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n"));
235 /* now for the real call to tdb_pack() */
236 /* one time to get the size needed */
237 buflen
= tdb_pack(*buf
, len
, TDB_FORMAT_STRING
,
239 sampass
->logoff_time
,
240 sampass
->kickoff_time
,
241 sampass
->pass_last_set_time
,
242 sampass
->pass_can_change_time
,
243 sampass
->pass_must_change_time
,
264 MAX_HOURS_LEN
, sampass
->hours
,
269 /* check to make sure we got it correct */
280 /***************************************************************
281 Open the TDB account SAM fo renumeration.
282 ****************************************************************/
283 BOOL
pdb_setsampwent(BOOL update
)
287 pstrcpy (tdbfile
, lp_private_dir());
288 pstrcat (tdbfile
, "/passdb.tdb");
290 /* Open tdb passwd */
291 if (!(global_tdb_ent
.passwd_tdb
= tdb_open(tdbfile
, 0, 0, update
? O_RDWR
: O_RDONLY
, 0600)))
293 DEBUG(0, ("Unable to open TDB passwd, trying create new!\n"));
294 if (!(global_tdb_ent
.passwd_tdb
= tdb_open(tdbfile
, 0, 0, O_RDWR
| O_CREAT
| O_EXCL
, 0600)))
296 DEBUG(0, ("Unable to create TDB passwd (smbpasswd.tdb) !!!"));
301 global_tdb_ent
.key
= tdb_firstkey(global_tdb_ent
.passwd_tdb
);
306 /***************************************************************
307 End enumeration of the TDB passwd list.
308 ****************************************************************/
309 void pdb_endsampwent(void)
311 if (global_tdb_ent
.passwd_tdb
)
313 tdb_close(global_tdb_ent
.passwd_tdb
);
314 global_tdb_ent
.passwd_tdb
= NULL
;
317 DEBUG(7, ("endtdbpwent: closed password file.\n"));
321 /*****************************************************************
322 Get one SAM_ACCOUNT from the TDB (next in line)
323 *****************************************************************/
324 SAM_ACCOUNT
* pdb_getsampwent(void)
329 /* do we have an valid interation pointer? */
330 if(global_tdb_ent
.passwd_tdb
== NULL
)
332 DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n"));
336 data
= tdb_fetch (global_tdb_ent
.passwd_tdb
, global_tdb_ent
.key
);
339 DEBUG(5,("pdb_getsampwent: database entry not found.\n"));
343 /* unpack the buffer */
344 pdb_clear_sam (&global_sam_pass
);
345 if (!init_sam_from_buffer (&global_sam_pass
, data
.dptr
, data
.dsize
))
347 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
351 /* validate the account and fill in UNIX uid and gid. sys_getpwnam()
352 is used instaed of Get_Pwnam() as we do not need to try case
354 if ((pw
=sys_getpwnam(pdb_get_username(&global_sam_pass
))) == NULL
)
356 DEBUG(0,("pdb_getsampwent: getpwnam(%s) return NULL. User does not exist!\n",
357 pdb_get_username(&global_sam_pass
)));
361 pdb_set_uid (&global_sam_pass
, pw
->pw_uid
);
362 pdb_set_gid (&global_sam_pass
, pw
->pw_gid
);
364 /* increment to next in line */
365 global_tdb_ent
.key
= tdb_nextkey (global_tdb_ent
.passwd_tdb
, global_tdb_ent
.key
);
367 return (&global_sam_pass
);
370 /******************************************************************
371 Lookup a name in the SAM TDB
372 ******************************************************************/
373 SAM_ACCOUNT
* pdb_getsampwnam (char *name
)
375 TDB_CONTEXT
*pwd_tdb
;
381 pstrcpy (tdbfile
, lp_private_dir());
382 pstrcat (tdbfile
, "/passdb.tdb");
385 slprintf(keystr
, sizeof(keystr
), "%s%s", USERPREFIX
, name
);
387 key
.dsize
= strlen (keystr
) + 1;
389 /* open the accounts TDB */
390 if (!(pwd_tdb
= tdb_open(tdbfile
, 0, 0, O_RDONLY
, 0600)))
392 DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd!\n"));
397 data
= tdb_fetch (pwd_tdb
, key
);
400 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
401 DEBUGADD(5, (" Error: %s\n", tdb_error(pwd_tdb
)));
406 /* unpack the buffer */
407 pdb_clear_sam (&global_sam_pass
);
408 if (!init_sam_from_buffer (&global_sam_pass
, data
.dptr
, data
.dsize
))
410 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
414 /* validate the account and fill in UNIX uid and gid. sys_getpwnam()
415 is used instaed of Get_Pwnam() as we do not need to try case
417 if ((pw
=sys_getpwnam(pdb_get_username(&global_sam_pass
))) == NULL
)
419 DEBUG(0,("pdb_getsampwent: getpwnam(%s) return NULL. User does not exist!\n",
420 pdb_get_username(&global_sam_pass
)));
424 pdb_set_uid (&global_sam_pass
, pw
->pw_uid
);
425 pdb_set_gid (&global_sam_pass
, pw
->pw_gid
);
430 return (&global_sam_pass
);
433 /***************************************************************************
436 I now know what the 'T' stands for in TDB :-( This is an unacceptable
437 solution. We need multiple indexes and transactional support. I'm
438 including this implementation only as an example.
439 **************************************************************************/
440 SAM_ACCOUNT
* pdb_getsampwuid (uid_t uid
)
442 SAM_ACCOUNT
*pw
= NULL
;
444 if (!pdb_setsampwent(False
))
447 while ( ((pw
=pdb_getsampwent()) != NULL
) && (pdb_get_uid(pw
) != uid
) )
455 /***************************************************************************
457 **************************************************************************/
458 SAM_ACCOUNT
* pdb_getsampwrid (uint32 rid
)
460 SAM_ACCOUNT
*pw
= NULL
;
462 if (!pdb_setsampwent(False
))
465 while ( ((pw
=pdb_getsampwent()) != NULL
) && (pdb_get_user_rid(pw
) != rid
) )
474 /***************************************************************************
476 ****************************************************************************/
477 BOOL
pdb_delete_sam_account(char *name
)
479 TDB_CONTEXT
*pwd_tdb
;
484 pstrcpy (tdbfile
, lp_private_dir());
485 pstrcat (tdbfile
, "/passdb.tdb");
489 if (!(pwd_tdb
= tdb_open(tdbfile
, 0, 0, O_RDWR
, 0600)))
491 DEBUG(0, ("Unable to open TDB passwd!"));
495 /* set the search key */
496 slprintf(keystr
, sizeof(keystr
), "%s%s", USERPREFIX
, name
);
498 key
.dsize
= strlen (keystr
) + 1;
500 /* it's outaa here! 8^) */
501 if (tdb_delete(pwd_tdb
, key
) != TDB_SUCCESS
)
503 DEBUG(5, ("Error deleting entry from tdb database!\n"));
504 DEBUGADD(5, (" Error: %s\n", tdb_error(pwd_tdb
)));
513 /***************************************************************************
515 ****************************************************************************/
516 static BOOL
tdb_update_sam(SAM_ACCOUNT
* newpwd
, BOOL override
, int flag
)
518 TDB_CONTEXT
*pwd_tdb
;
524 pstrcpy (tdbfile
, lp_private_dir());
525 pstrcat (tdbfile
, "/passdb.tdb");
527 if ( (!newpwd
->uid
) || (!newpwd
->gid
) )
529 DEBUG (0,("tdb_update_sam: Attempting to store a SAM_ACCOUNT for [%s] with no uid/gid!\n", newpwd
->username
));
533 /* if we don't have a RID, then generate one */
534 if (!newpwd
->user_rid
)
535 pdb_set_user_rid (pdb_uid_to_user_rid (newpwd
->uid
));
536 if (!newpwd
->group_rid
)
537 pdb_set_user_rid (pdb_uid_to_group_rid (newpwd
->gid
));
539 /* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */
540 if ((data
.dsize
=init_buffer_from_sam (&buf
, newpwd
)) == -1)
542 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n"));
547 /* setup the index key */
548 slprintf(keystr
, sizeof(keystr
), "%s%s", USERPREFIX
, pdb_get_username(newpwd
));
550 key
.dsize
= strlen (keystr
) + 1;
552 /* invalidate the existing TDB iterator if it is open */
553 if (global_tdb_ent
.passwd_tdb
)
555 tdb_close(global_tdb_ent
.passwd_tdb
);
556 global_tdb_ent
.passwd_tdb
= NULL
;
559 /* open the account TDB */
560 if (!(pwd_tdb
= tdb_open(tdbfile
, 0, 0, O_RDWR
, 0600)))
562 DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd!\n"));
563 if (flag
== TDB_INSERT
)
565 DEBUG(0, ("Unable to open TDB passwd, trying create new!\n"));
566 if (!(pwd_tdb
= tdb_open(tdbfile
, 0, 0, O_RDWR
| O_CREAT
| O_EXCL
, 0600)))
568 DEBUG(0, ("Unable to create TDB passwd (smbpasswd.tdb) !!!\n"));
574 /* add the account */
575 if (tdb_store(pwd_tdb
, key
, data
, flag
) != TDB_SUCCESS
)
577 DEBUG(0, ("Unable to modify TDB passwd!"));
578 DEBUGADD(0, (" Error: %s\n", tdb_error (pwd_tdb
)));
589 /***************************************************************************
590 Modifies an existing SAM_ACCOUNT
591 ****************************************************************************/
592 BOOL
pdb_update_sam_account (SAM_ACCOUNT
*newpwd
, BOOL override
)
594 return (tdb_update_sam(newpwd
, override
, TDB_MODIFY
));
597 /***************************************************************************
598 Adds an existing SAM_ACCOUNT
599 ****************************************************************************/
600 BOOL
pdb_add_sam_account (SAM_ACCOUNT
*newpwd
)
602 return (tdb_update_sam(newpwd
, True
, TDB_INSERT
));
607 /* Do *NOT* make this function static. It breaks the compile on gcc. JRA */
608 void samtdb_dummy_function(void) { } /* stop some compilers complaining */
609 #endif /* WITH_TDBPWD */