2 * Unix SMB/Netbios implementation. Version 1.9. tdbedit module. Copyright
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 675
17 * Mass Ave, Cambridge, MA 02139, USA.
20 /* base uid for trust accounts is set to 60000 !
21 * May be we should add the defines in smb.h to make it possible having
22 * different values on different platforms?
25 #define BASE_MACHINE_UID 60000
26 #define MAX_MACHINE_UID 65500 /* 5500 trust acconts aren't enough? */
30 extern pstring global_myname
;
31 extern int DEBUGLEVEL
;
34 * Next two lines needed for SunOS and don't
35 * hurt anything else...
40 /*********************************************************
41 Print command usage on stderr and die.
42 **********************************************************/
43 static void usage(void)
46 printf("tdbedit options\n");
48 printf("You need to be root to use this tool!\n");
50 printf("(actually to add a user you need to use smbpasswd)\n");
52 printf(" -l list usernames\n");
53 printf(" -v verbose output\n");
54 printf(" -w smbpasswd file style\n");
55 printf(" -u username print user's info\n");
56 printf(" -f fullname set Full Name\n");
57 printf(" -h homedir set home directory\n");
58 printf(" -d drive set home dir drive\n");
59 printf(" -s script set logon script\n");
60 printf(" -p profile set profile path\n");
61 printf(" -a create new account\n");
62 printf(" -m it is a machine trust\n");
63 printf(" -x delete this user\n");
64 printf(" -i file import account from file (smbpasswd style)\n");
67 /*********************************************************
68 Print info from sam structure
69 **********************************************************/
70 static int print_sam_info (SAM_ACCOUNT
*sam_pwent
, BOOL verbosity
, BOOL smbpwdstyle
)
72 /* TODO: chaeck if entry is a user or a workstation */
73 if (!sam_pwent
) return -1;
77 printf ("username: %s\n", sam_pwent
->username
);
78 printf ("user ID/Group: %d/%d\n", sam_pwent
->uid
,
80 printf ("user RID/GRID: %d/%d\n", sam_pwent
->user_rid
,
81 sam_pwent
->group_rid
);
82 printf ("Full Name: %s\n", sam_pwent
->full_name
);
83 printf ("Home Directory: %s\n", sam_pwent
->home_dir
);
84 printf ("HomeDir Drive: %s\n", sam_pwent
->dir_drive
);
85 printf ("Logon Script: %s\n", sam_pwent
->logon_script
);
86 printf ("Profile Path: %s\n", sam_pwent
->profile_path
);
92 pdb_sethexpwd(lm_passwd
, pdb_get_lanman_passwd(sam_pwent
), pdb_get_acct_ctrl(sam_pwent
));
93 pdb_sethexpwd(nt_passwd
, pdb_get_nt_passwd(sam_pwent
), pdb_get_acct_ctrl(sam_pwent
));
95 printf ("%s:%d:%s:%s:%s:LCT-%08x:\n",
96 pdb_get_username(sam_pwent
),
97 pdb_get_uid(sam_pwent
),
100 pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent
),NEW_PW_FORMAT_SPACE_PADDED_LEN
),
101 (uint32
)pdb_get_pass_last_set_time(sam_pwent
));
105 printf ("%s:%d:%s\n", sam_pwent
->username
, sam_pwent
->uid
, sam_pwent
->full_name
);
111 /*********************************************************
112 Get an Print User Info
113 **********************************************************/
114 static int print_user_info (char *username
, BOOL verbosity
, BOOL smbpwdstyle
)
116 SAM_ACCOUNT
*sam_pwent
=NULL
;
119 pdb_init_sam(&sam_pwent
);
121 ret
= pdb_getsampwnam (sam_pwent
, username
);
124 fprintf (stderr
, "Username not found!\n");
125 pdb_free_sam(sam_pwent
);
129 ret
=print_sam_info (sam_pwent
, verbosity
, smbpwdstyle
);
130 pdb_free_sam(sam_pwent
);
135 /*********************************************************
137 **********************************************************/
138 static int print_users_list (BOOL verbosity
, BOOL smbpwdstyle
)
140 SAM_ACCOUNT
*sam_pwent
=NULL
;
143 pdb_init_sam(&sam_pwent
);
145 ret
= pdb_setsampwent(False
);
146 if (ret
&& errno
== ENOENT
) {
147 fprintf (stderr
,"Password database not found!\n");
148 pdb_free_sam(sam_pwent
);
152 while ((ret
= pdb_getsampwent (sam_pwent
)))
154 if (verbosity
) printf ("---------------\n");
155 print_sam_info (sam_pwent
, verbosity
, smbpwdstyle
);
156 pdb_reset_sam(sam_pwent
);
160 pdb_free_sam(sam_pwent
);
164 /*********************************************************
166 **********************************************************/
167 static int set_user_info (char *username
, char *fullname
, char *homedir
, char *drive
, char *script
, char *profile
)
169 SAM_ACCOUNT
*sam_pwent
=NULL
;
172 pdb_init_sam(&sam_pwent
);
174 ret
= pdb_getsampwnam (sam_pwent
, username
);
177 fprintf (stderr
, "Username not found!\n");
178 pdb_free_sam(sam_pwent
);
182 if (fullname
) pdb_set_fullname(sam_pwent
, fullname
);
183 if (homedir
) pdb_set_homedir(sam_pwent
, homedir
);
184 if (drive
) pdb_set_dir_drive(sam_pwent
,drive
);
185 if (script
) pdb_set_logon_script(sam_pwent
, script
);
186 if (profile
) pdb_set_profile_path (sam_pwent
, profile
);
188 if (pdb_update_sam_account (sam_pwent
, TRUE
)) print_user_info (username
, TRUE
, FALSE
);
191 fprintf (stderr
, "Unable to modify entry!\n");
192 pdb_free_sam(sam_pwent
);
195 pdb_free_sam(sam_pwent
);
199 /*********************************************************
201 **********************************************************/
202 static int new_user (char *username
, char *fullname
, char *homedir
, char *drive
, char *script
, char *profile
)
204 SAM_ACCOUNT sam_pwent
;
205 struct passwd
*pwd
= NULL
;
207 uchar new_nt_p16
[16];
208 char *password1
, *password2
;
210 ZERO_STRUCT(sam_pwent
);
212 if (pdb_getsampwnam (&sam_pwent
, username
))
214 fprintf (stderr
, "Username already exist in database!\n");
218 if (!(pwd
= sys_getpwnam(username
)))
220 fprintf (stderr
, "User %s does not exist in system passwd!\n", username
);
224 password1
= getpass("new password:");
225 password2
= getpass("retype new password:");
226 if (strcmp (password1
, password2
))
228 fprintf (stderr
, "Passwords does not match!\n");
231 nt_lm_owf_gen (password1
, new_nt_p16
, new_p16
);
233 pdb_set_username(&sam_pwent
, username
);
234 if (fullname
) pdb_set_fullname(&sam_pwent
, fullname
);
235 if (homedir
) pdb_set_homedir (&sam_pwent
, homedir
);
236 if (drive
) pdb_set_dir_drive (&sam_pwent
, drive
);
237 if (script
) pdb_set_logon_script(&sam_pwent
, script
);
238 if (profile
) pdb_set_profile_path (&sam_pwent
, profile
);
240 /* TODO: Check uid not being in MACHINE UID range!! */
241 sam_pwent
.uid
= pwd
->pw_uid
;
242 sam_pwent
.gid
= pwd
->pw_gid
;
243 sam_pwent
.user_rid
= pdb_uid_to_user_rid (pwd
->pw_uid
);
244 sam_pwent
.group_rid
= pdb_gid_to_group_rid (pwd
->pw_gid
);
245 sam_pwent
.lm_pw
= new_p16
;
246 sam_pwent
.nt_pw
= new_nt_p16
;
247 sam_pwent
.acct_ctrl
= ACB_NORMAL
;
249 if (pdb_add_sam_account (&sam_pwent
)) print_user_info (username
, TRUE
, FALSE
);
252 fprintf (stderr
, "Unable to add user!\n");
258 /*********************************************************
260 **********************************************************/
261 static int new_machine (char *machinename
)
263 SAM_ACCOUNT sam_pwent
;
264 SAM_ACCOUNT sam_trust
;
266 uchar new_nt_p16
[16];
268 char *password
= NULL
;
271 if (machinename
[strlen (machinename
) -1] == '$') machinename
[strlen (machinename
) -1] = '\0';
273 safe_strcpy (name
, machinename
, 16);
274 safe_strcat (name
, "$", 16);
276 string_set (&password
, machinename
);
278 nt_lm_owf_gen (password
, new_nt_p16
, new_p16
);
280 pdb_set_username(&sam_pwent
, name
);
282 for (uid
=BASE_MACHINE_UID
; uid
<=MAX_MACHINE_UID
; uid
++)
283 if (!(pdb_getsampwuid (&sam_trust
, uid
)))
286 if (uid
>MAX_MACHINE_UID
) {
287 fprintf (stderr
, "No more free UIDs available to Machine accounts!\n");
292 sam_pwent
.gid
= BASE_MACHINE_UID
; /* TODO: set there more appropriate value!! */
293 sam_pwent
.user_rid
= pdb_uid_to_user_rid (uid
);
294 sam_pwent
.group_rid
= pdb_gid_to_group_rid (BASE_MACHINE_UID
);
295 sam_pwent
.lm_pw
= new_p16
;
296 sam_pwent
.nt_pw
= new_nt_p16
;
297 sam_pwent
.acct_ctrl
= ACB_WSTRUST
;
299 if (pdb_add_sam_account (&sam_pwent
))
300 print_user_info (name
, TRUE
, FALSE
);
302 fprintf (stderr
, "Unable to add machine!\n");
308 /*********************************************************
310 **********************************************************/
311 static int delete_user_entry (char *username
)
313 return pdb_delete_sam_account (username
);
316 /*********************************************************
318 **********************************************************/
319 static int delete_machine_entry (char *machinename
)
323 safe_strcpy (name
, machinename
, 16);
324 if (name
[strlen(name
)] != '$')
326 safe_strcat (name
, "$", 16);
328 return pdb_delete_sam_account (name
);
331 /*********************************************************
332 Import smbpasswd style file
333 **********************************************************/
334 static int import_users (char *filename
)
337 SAM_ACCOUNT sam_pwent
;
338 SAM_ACCOUNT sam_test
;
339 static pstring user_name
;
340 static unsigned char smbpwd
[16];
341 static unsigned char smbntpwd
[16];
350 if((fp
= sys_fopen(filename
, "rb")) == NULL
)
352 fprintf (stderr
, "%s\n", strerror (ferror (fp
)));
360 fgets(linebuf
, 256, fp
);
363 fprintf (stderr
, "%s\n", strerror (ferror (fp
)));
366 if ((linebuf_len
= strlen(linebuf
)) == 0)
371 if (linebuf
[linebuf_len
- 1] != '\n')
374 while (!ferror(fp
) && !feof(fp
))
377 if (c
== '\n') break;
380 else linebuf
[linebuf_len
- 1] = '\0';
381 linebuf
[linebuf_len
] = '\0';
382 if ((linebuf
[0] == 0) && feof(fp
))
388 if (linebuf
[0] == '#' || linebuf
[0] == '\0') continue;
390 /*pdb_init_sam (&sam_pwent);*/
391 sam_pwent
.acct_ctrl
= ACB_NORMAL
;
394 p
= (unsigned char *) strchr(linebuf
, ':');
397 fprintf (stderr
, "Error: malformed password entry at line %d !!\n", line
);
400 strncpy(user_name
, linebuf
, PTR_DIFF(p
, linebuf
));
401 user_name
[PTR_DIFF(p
, linebuf
)] = '\0';
407 fprintf (stderr
, "Error: negative uid at line %d\n", line
);
412 fprintf (stderr
, "Error: malformed password entry at line %d (uid not number)\n", line
);
415 uidval
= atoi((char *) p
);
416 while (*p
&& isdigit(*p
)) p
++;
419 fprintf (stderr
, "Error: malformed password entry at line %d (no : after uid)\n", line
);
423 pdb_set_username(&sam_pwent
, user_name
);
424 pdb_set_uid (&sam_pwent
, uidval
);
428 if (*p
== '*' || *p
== 'X')
430 /* Password deliberately invalid */
431 fprintf (stderr
, "Warning: entry invalidated for user %s\n", user_name
);
432 sam_pwent
.lm_pw
= NULL
;
433 sam_pwent
.nt_pw
= NULL
;
434 sam_pwent
.acct_ctrl
|= ACB_DISABLED
;
438 if (linebuf_len
< (PTR_DIFF(p
, linebuf
) + 33))
440 fprintf (stderr
, "Error: malformed password entry at line %d (password too short)\n",line
);
445 fprintf (stderr
, "Error: malformed password entry at line %d (no terminating :)\n",line
);
448 if (!strncasecmp((char *) p
, "NO PASSWORD", 11))
450 sam_pwent
.lm_pw
= NULL
;
451 sam_pwent
.acct_ctrl
|= ACB_PWNOTREQ
;
455 if (!pdb_gethexpwd((char *)p
, smbpwd
))
457 fprintf (stderr
, "Error: malformed Lanman password entry at line %d (non hex chars)\n", line
);
460 sam_pwent
.lm_pw
= smbpwd
;
463 sam_pwent
.nt_pw
= NULL
;
465 if ((linebuf_len
>= (PTR_DIFF(p
, linebuf
) + 33)) && (p
[32] == ':'))
467 if (*p
!= '*' && *p
!= 'X')
469 if (pdb_gethexpwd((char *)p
,smbntpwd
))
471 sam_pwent
.nt_pw
= smbntpwd
;
478 /* Get ACCT_CTRL field if any */
481 unsigned char *end_p
= (unsigned char *)strchr((char *)p
, ']');
483 sam_pwent
.acct_ctrl
= pdb_decode_acct_ctrl((char*)p
);
484 if(sam_pwent
.acct_ctrl
== 0) sam_pwent
.acct_ctrl
= ACB_NORMAL
;
486 /* Get last change time */
487 if(end_p
) p
= end_p
+ 1;
491 if(*p
&& (StrnCaseCmp((char *)p
, "LCT-", 4)==0))
496 for(i
= 0; i
< 8; i
++)
498 if(p
[i
] == '\0' || !isxdigit(p
[i
])) break;
502 sam_pwent
.pass_last_set_time
= (time_t)strtol((char *)p
, NULL
, 16);
508 /* Test if workstation */
511 if(sam_pwent
.username
[strlen(sam_pwent
.username
) - 1] == '$')
513 sam_pwent
.acct_ctrl
&= ~ACB_NORMAL
;
514 sam_pwent
.acct_ctrl
|= ACB_WSTRUST
;
517 if (sam_pwent
.acct_ctrl
& ACB_WSTRUST
)
519 if (!(BASE_MACHINE_UID
<= uidval
<= MAX_MACHINE_UID
))
521 fprintf (stderr
, "Warning: Machine UID out of normal range %d-%d\n",
525 sam_pwent
.gid
= BASE_MACHINE_UID
;
528 /* Test if user is valid */
529 if (sam_pwent
.acct_ctrl
& ACB_NORMAL
)
531 struct passwd
*pwd
= NULL
;
533 if (pdb_getsampwnam (&sam_test
,user_name
))
535 fprintf (stderr
, "Error: Username already exist in database!\n");
538 if (!(pwd
= sys_getpwnam(user_name
)))
540 fprintf (stderr
, "Error: User %s does not exist in system passwd!\n", user_name
);
543 sam_pwent
.gid
= pwd
->pw_gid
;
546 /* Fill in sam_pwent structure */
547 sam_pwent
.user_rid
= pdb_uid_to_user_rid (sam_pwent
.uid
);
548 sam_pwent
.group_rid
= pdb_gid_to_group_rid (sam_pwent
.gid
);
549 /* TODO: set also full_name, home_dir, dir_drive, logon_script, profile_path, ecc...
550 * when defaults will be available (after passdb redesign)
551 * let them blank just now they are not used anyway
554 /* Now ADD the entry */
555 if (!(pdb_add_sam_account (&sam_pwent
)))
557 fprintf (stderr
, "Unable to add user entry!\n");
560 printf ("%s imported!\n", user_name
);
563 printf ("%d lines read.\n%d entryes imported\n", line
, good
);
568 /*********************************************************
570 **********************************************************/
571 int main (int argc
, char **argv
)
574 static pstring servicesf
= CONFIGFILE
;
575 BOOL list_users
= FALSE
;
576 BOOL verbose
= FALSE
;
577 BOOL spstyle
= FALSE
;
578 BOOL setparms
= FALSE
;
579 BOOL machine
= FALSE
;
580 BOOL add_user
= FALSE
;
581 BOOL delete_user
= FALSE
;
583 char *user_name
= NULL
;
584 char *full_name
= NULL
;
585 char *home_dir
= NULL
;
586 char *home_drive
= NULL
;
587 char *logon_script
= NULL
;
588 char *profile_path
= NULL
;
589 char *smbpasswd
= NULL
;
593 setup_logging("tdbedit", True
);
595 charset_initialise();
604 if(!initialize_password_db(True
)) {
605 fprintf(stderr
, "Can't setup password database vectors.\n");
609 if (!lp_load(servicesf
,True
,False
,False
)) {
610 fprintf(stderr
, "Can't load %s - run testparm to debug it\n",
615 while ((ch
= getopt(argc
, argv
, "ad:f:h:i:lmp:s:u:vwx")) != EOF
) {
649 logon_script
= optarg
;
653 profile_path
= optarg
;
666 if (((add_user
?1:0) + (delete_user
?1:0) + (list_users
?1:0) + (import
?1:0) + (setparms
?1:0)) > 1)
668 fprintf (stderr
, "Incompatible options on command line!\n");
677 fprintf (stderr
, "Username not specified! (use -u option)\n");
680 if (machine
) return new_machine (user_name
);
681 else return new_user (user_name
, full_name
, home_dir
, home_drive
, logon_script
, profile_path
);
688 fprintf (stderr
, "Username not specified! (use -u option)\n");
691 if (machine
) return delete_machine_entry (user_name
);
692 else return delete_user_entry (user_name
);
697 if (setparms
) set_user_info ( user_name
,
704 else return print_user_info (user_name
, verbose
, spstyle
);
711 return print_users_list (verbose
, spstyle
);
714 return import_users (smbpasswd
);