Removed unused variable.
[kai/samba.git] / source / utils / pdbedit.c
1 /*
2  * Unix SMB/Netbios implementation. Version 1.9. tdbedit module. Copyright
3  * (C) Simo Sorce 2000
4  * 
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)
8  * any later version.
9  * 
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
13  * more details.
14  * 
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.
18  */
19
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?
23  */
24
25 #define BASE_MACHINE_UID 60000
26 #define MAX_MACHINE_UID 65500 /* 5500 trust acconts aren't enough? */
27
28 #include "includes.h"
29
30 extern pstring global_myname;
31 extern int DEBUGLEVEL;
32
33 /*
34  * Next two lines needed for SunOS and don't
35  * hurt anything else...
36  */
37 extern char *optarg;
38 extern int optind;
39
40 /*********************************************************
41  Print command usage on stderr and die.
42 **********************************************************/
43 static void usage(void)
44 {
45         if (getuid() == 0) {
46                 printf("tdbedit options\n");
47         } else {
48                 printf("You need to be root to use this tool!\n");
49         }
50         printf("(actually to add a user you need to use smbpasswd)\n");
51         printf("options:\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");
65         exit(1);
66 }
67 /*********************************************************
68  Print info from sam structure
69 **********************************************************/
70 static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdstyle)
71 {
72         /* TODO: chaeck if entry is a user or a workstation */
73         if (!sam_pwent) return -1;
74         
75         if (verbosity)
76         {
77                 printf ("username:       %s\n", sam_pwent->username);
78                 printf ("user ID/Group:  %d/%d\n", sam_pwent->uid,
79                                                   sam_pwent->gid);
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);
87         }
88         else if (smbpwdstyle)
89         {
90                 char lm_passwd[33];
91                 char nt_passwd[33];
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));
94                 
95                 printf ("%s:%d:%s:%s:%s:LCT-%08x:\n",
96                         pdb_get_username(sam_pwent),
97                         pdb_get_uid(sam_pwent),
98                         lm_passwd,
99                         nt_passwd,
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));
102         }
103         else
104         {
105                 printf ("%s:%d:%s\n", sam_pwent->username, sam_pwent->uid, sam_pwent->full_name);
106         }       
107         
108         return 0;       
109 }
110
111 /*********************************************************
112  Get an Print User Info
113 **********************************************************/
114 static int print_user_info (char *username, BOOL verbosity, BOOL smbpwdstyle)
115 {
116         SAM_ACCOUNT *sam_pwent=NULL;
117         BOOL ret;
118         
119         pdb_init_sam(&sam_pwent);
120         
121         ret = pdb_getsampwnam (sam_pwent, username);
122
123         if (ret==False) {
124                 fprintf (stderr, "Username not found!\n");
125                 pdb_clear_sam(sam_pwent);
126                 return -1;
127         }
128         
129         ret=print_sam_info (sam_pwent, verbosity, smbpwdstyle);
130         pdb_clear_sam(sam_pwent);
131         
132         return ret;
133 }
134         
135 /*********************************************************
136  List Users
137 **********************************************************/
138 static int print_users_list (BOOL verbosity, BOOL smbpwdstyle)
139 {
140         SAM_ACCOUNT *sam_pwent=NULL;
141         BOOL ret;
142         
143         pdb_init_sam(&sam_pwent);
144
145         ret = pdb_setsampwent(False);
146         if (ret && errno == ENOENT) {
147                 fprintf (stderr,"Password database not found!\n");
148                 pdb_clear_sam(sam_pwent);
149                 exit(1);
150         }
151
152         while ((ret = pdb_getsampwent (sam_pwent)))
153         {
154                 if (verbosity) printf ("---------------\n");
155                 print_sam_info (sam_pwent, verbosity, smbpwdstyle);
156         }
157         
158         pdb_endsampwent ();
159         pdb_clear_sam(sam_pwent);
160         return 0;
161 }
162
163 /*********************************************************
164  Set User Info
165 **********************************************************/
166 static int set_user_info (char *username, char *fullname, char *homedir, char *drive, char *script, char *profile)
167 {
168         SAM_ACCOUNT *sam_pwent=NULL;
169         BOOL ret;
170         
171         pdb_init_sam(&sam_pwent);
172         
173         ret = pdb_getsampwnam (sam_pwent, username);
174         if (ret==False)
175         {
176                 fprintf (stderr, "Username not found!\n");
177                 pdb_clear_sam(sam_pwent);
178                 return -1;
179         }
180         
181         if (fullname) pdb_set_fullname(sam_pwent, fullname);
182         if (homedir) pdb_set_homedir(sam_pwent, homedir);
183         if (drive) pdb_set_dir_drive(sam_pwent,drive);
184         if (script) pdb_set_logon_script(sam_pwent, script);
185         if (profile) pdb_set_profile_path (sam_pwent, profile);
186         
187         if (pdb_update_sam_account (sam_pwent, TRUE)) print_user_info (username, TRUE, FALSE);
188         else
189         {
190                 fprintf (stderr, "Unable to modify entry!\n");
191                 pdb_clear_sam(sam_pwent);
192                 return -1;
193         }
194         pdb_clear_sam(sam_pwent);
195         return 0;
196 }
197
198 /*********************************************************
199  Add New User
200 **********************************************************/
201 static int new_user (char *username, char *fullname, char *homedir, char *drive, char *script, char *profile)
202 {
203         SAM_ACCOUNT sam_pwent;
204         struct passwd  *pwd = NULL;
205         uchar new_p16[16];
206         uchar new_nt_p16[16];
207         char *password1, *password2;
208         
209         ZERO_STRUCT(sam_pwent);
210
211         if (pdb_getsampwnam (&sam_pwent, username))
212         {
213                 fprintf (stderr, "Username already exist in database!\n");
214                 return -1;
215         }
216
217         if (!(pwd = sys_getpwnam(username)))
218         {
219                 fprintf (stderr, "User %s does not exist in system passwd!\n", username);
220                 return -1;
221         }
222         
223         password1 = getpass("new password:");
224         password2 = getpass("retype new password:");
225         if (strcmp (password1, password2))
226         {
227                  fprintf (stderr, "Passwords does not match!\n");
228                  return -1;
229         }
230         nt_lm_owf_gen (password1, new_nt_p16, new_p16);
231         
232         pdb_set_username(&sam_pwent, username);
233         if (fullname) pdb_set_fullname(&sam_pwent, fullname);
234         if (homedir) pdb_set_homedir (&sam_pwent, homedir);
235         if (drive) pdb_set_dir_drive (&sam_pwent, drive);
236         if (script) pdb_set_logon_script(&sam_pwent, script);
237         if (profile) pdb_set_profile_path (&sam_pwent, profile);
238         
239         /* TODO: Check uid not being in MACHINE UID range!! */
240         sam_pwent.uid = pwd->pw_uid;
241         sam_pwent.gid = pwd->pw_gid;
242         sam_pwent.user_rid = pdb_uid_to_user_rid (pwd->pw_uid);
243         sam_pwent.group_rid = pdb_gid_to_group_rid (pwd->pw_gid);
244         sam_pwent.lm_pw = new_p16;
245         sam_pwent.nt_pw = new_nt_p16;
246         sam_pwent.acct_ctrl = ACB_NORMAL;
247         
248         if (pdb_add_sam_account (&sam_pwent)) print_user_info (username, TRUE, FALSE);
249         else
250         {
251                 fprintf (stderr, "Unable to add user!\n");
252                 return -1;
253         }
254         return 0;
255 }
256
257 /*********************************************************
258  Add New Machine
259 **********************************************************/
260 static int new_machine (char *machinename)
261 {
262         SAM_ACCOUNT sam_pwent;
263         SAM_ACCOUNT sam_trust;
264         uchar new_p16[16];
265         uchar new_nt_p16[16];
266         char name[16];
267         char *password = NULL;
268         uid_t uid;
269
270         if (machinename[strlen (machinename) -1] == '$') machinename[strlen (machinename) -1] = '\0';
271         
272         safe_strcpy (name, machinename, 16);
273         safe_strcat (name, "$", 16);
274         
275         string_set (&password, machinename);
276         strlower(password);
277         nt_lm_owf_gen (password, new_nt_p16, new_p16);
278         
279         pdb_set_username(&sam_pwent, name);
280         
281         for (uid=BASE_MACHINE_UID; uid<=MAX_MACHINE_UID; uid++)
282                 if (!(pdb_getsampwuid (&sam_trust, uid)))
283                         break;
284
285         if (uid>MAX_MACHINE_UID) {
286                 fprintf (stderr, "No more free UIDs available to Machine accounts!\n");
287                 return -1;
288         }
289
290         sam_pwent.uid = uid;
291         sam_pwent.gid = BASE_MACHINE_UID; /* TODO: set there more appropriate value!! */
292         sam_pwent.user_rid = pdb_uid_to_user_rid (uid);
293         sam_pwent.group_rid = pdb_gid_to_group_rid (BASE_MACHINE_UID);
294         sam_pwent.lm_pw = new_p16;
295         sam_pwent.nt_pw = new_nt_p16;
296         sam_pwent.acct_ctrl = ACB_WSTRUST;
297         
298         if (pdb_add_sam_account (&sam_pwent))
299                 print_user_info (name, TRUE, FALSE);
300         else {
301                 fprintf (stderr, "Unable to add machine!\n");
302                 return -1;
303         }
304         return 0;
305 }
306
307 /*********************************************************
308  Delete user entry
309 **********************************************************/
310 static int delete_user_entry (char *username)
311 {
312         return pdb_delete_sam_account (username);
313 }
314
315 /*********************************************************
316  Delete machine entry
317 **********************************************************/
318 static int delete_machine_entry (char *machinename)
319 {
320         char name[16];
321         
322         safe_strcpy (name, machinename, 16);
323         if (name[strlen(name)] != '$')
324         {
325                 safe_strcat (name, "$", 16);
326         }
327         return pdb_delete_sam_account (name);
328 }
329
330 /*********************************************************
331  Import smbpasswd style file
332 **********************************************************/
333 static int import_users (char *filename)
334 {
335         FILE *fp = NULL;
336         SAM_ACCOUNT sam_pwent;
337         SAM_ACCOUNT sam_test;
338         static pstring  user_name;
339         static unsigned char smbpwd[16];
340         static unsigned char smbntpwd[16];
341         char linebuf[256];
342         size_t linebuf_len;
343         unsigned char c;
344         unsigned char *p;
345         long uidval;
346         int line = 0;
347         int good = 0;
348
349         if((fp = sys_fopen(filename, "rb")) == NULL)
350         {
351                 fprintf (stderr, "%s\n", strerror (ferror (fp)));
352                 return -1;
353         }
354         
355         while (!feof(fp))
356         {
357                 /*Get a new line*/
358                 linebuf[0] = '\0';
359                 fgets(linebuf, 256, fp);
360                 if (ferror(fp))
361                 {
362                         fprintf (stderr, "%s\n", strerror (ferror (fp)));
363                         return -1;
364                 }
365                 if ((linebuf_len = strlen(linebuf)) == 0)
366                 {
367                         line++;
368                         continue;
369                 }
370                 if (linebuf[linebuf_len - 1] != '\n')
371                 {
372                         c = '\0';
373                         while (!ferror(fp) && !feof(fp))
374                         {
375                                 c = fgetc(fp);
376                                 if (c == '\n') break;
377                         }
378                 }
379                 else linebuf[linebuf_len - 1] = '\0';
380                 linebuf[linebuf_len] = '\0';
381                 if ((linebuf[0] == 0) && feof(fp))
382                 {
383                         /*end of file!!*/
384                         return 0;
385                 }
386                 line++;
387                 if (linebuf[0] == '#' || linebuf[0] == '\0') continue;
388                 
389                 /*pdb_init_sam (&sam_pwent);*/
390                 sam_pwent.acct_ctrl = ACB_NORMAL;
391                 
392                 /* Get user name */
393                 p = (unsigned char *) strchr(linebuf, ':');
394                 if (p == NULL)
395                 {
396                         fprintf (stderr, "Error: malformed password entry at line %d !!\n", line);
397                         continue;
398                 }
399                 strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
400                 user_name[PTR_DIFF(p, linebuf)] = '\0';
401
402                 /* Get smb uid. */
403                 p++;
404                 if(*p == '-')
405                 {
406                         fprintf (stderr, "Error: negative uid at line %d\n", line);
407                         continue;
408                 }
409                 if (!isdigit(*p))
410                 {
411                         fprintf (stderr, "Error: malformed password entry at line %d (uid not number)\n", line);
412                         continue;
413                 }
414                 uidval = atoi((char *) p);
415                 while (*p && isdigit(*p)) p++;
416                 if (*p != ':')
417                 {
418                         fprintf (stderr, "Error: malformed password entry at line %d (no : after uid)\n", line);
419                         continue;
420                 }
421
422                 pdb_set_username(&sam_pwent, user_name);
423                 pdb_set_uid (&sam_pwent, uidval);
424                 
425                 /* Get passwords */
426                 p++;
427                 if (*p == '*' || *p == 'X')
428                 {
429                         /* Password deliberately invalid */
430                         fprintf (stderr, "Warning: entry invalidated for user %s\n", user_name);
431                         sam_pwent.lm_pw = NULL;
432                         sam_pwent.nt_pw = NULL;
433                         sam_pwent.acct_ctrl |= ACB_DISABLED;
434                 }
435                 else
436                 {
437                         if (linebuf_len < (PTR_DIFF(p, linebuf) + 33))
438                         {
439                                 fprintf (stderr, "Error: malformed password entry at line %d (password too short)\n",line);
440                                 continue;
441                         }
442                         if (p[32] != ':')
443                         {
444                                 fprintf (stderr, "Error: malformed password entry at line %d (no terminating :)\n",line);
445                                 continue;
446                         }
447                         if (!strncasecmp((char *) p, "NO PASSWORD", 11))
448                         {
449                                 sam_pwent.lm_pw = NULL;
450                                 sam_pwent.acct_ctrl |= ACB_PWNOTREQ;
451                         }
452                         else
453                         {
454                                 if (!pdb_gethexpwd((char *)p, smbpwd))
455                                 {
456                                         fprintf (stderr, "Error: malformed Lanman password entry at line %d (non hex chars)\n", line);
457                                         continue;
458                                 }
459                                 sam_pwent.lm_pw = smbpwd;
460                         }
461                         /* NT password */
462                         sam_pwent.nt_pw = NULL;
463                         p += 33;
464                         if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':'))
465                         {
466                                 if (*p != '*' && *p != 'X')
467                                 {
468                                         if (pdb_gethexpwd((char *)p,smbntpwd))
469                                         {
470                                                 sam_pwent.nt_pw = smbntpwd;
471                                         }
472                                 }
473                                 p += 33;
474                         }
475                 }
476
477                 /* Get ACCT_CTRL field if any */
478                 if (*p == '[')
479                 {
480                         unsigned char *end_p = (unsigned char *)strchr((char *)p, ']');
481                         
482                         sam_pwent.acct_ctrl = pdb_decode_acct_ctrl((char*)p);
483                         if(sam_pwent.acct_ctrl == 0) sam_pwent.acct_ctrl = ACB_NORMAL;
484                         
485                         /* Get last change time */
486                         if(end_p) p = end_p + 1;
487                         if(*p == ':')
488                         {
489                                 p++;
490                                 if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0))
491                                 {
492                                         int i;
493                                         
494                                         p += 4;
495                                         for(i = 0; i < 8; i++)
496                                         {
497                                                 if(p[i] == '\0' || !isxdigit(p[i])) break;
498                                         }
499                                         if(i == 8)
500                                         {
501                                                 sam_pwent.pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
502                                         }
503                                 }
504                         }
505                 }
506
507                 /* Test if workstation */
508                 else
509                 {
510                         if(sam_pwent.username[strlen(sam_pwent.username) - 1] == '$')
511                         {
512                                 sam_pwent.acct_ctrl &= ~ACB_NORMAL;
513                                 sam_pwent.acct_ctrl |= ACB_WSTRUST;
514                         }
515                 }
516                 if (sam_pwent.acct_ctrl & ACB_WSTRUST)
517                 {
518                         if (!(BASE_MACHINE_UID <= uidval <= MAX_MACHINE_UID))
519                         {
520                                 fprintf (stderr, "Warning: Machine UID out of normal range %d-%d\n",
521                                                  BASE_MACHINE_UID,
522                                                  MAX_MACHINE_UID);
523                         }
524                         sam_pwent.gid = BASE_MACHINE_UID;
525                 }
526         
527                 /* Test if user is valid */
528                 if (sam_pwent.acct_ctrl & ACB_NORMAL)
529                 {
530                         struct passwd  *pwd = NULL;
531
532                         if (pdb_getsampwnam (&sam_test,user_name))
533                         {
534                                 fprintf (stderr, "Error: Username already exist in database!\n");
535                                 continue;
536                         }
537                         if (!(pwd = sys_getpwnam(user_name)))
538                         {
539                                 fprintf (stderr, "Error: User %s does not exist in system passwd!\n", user_name);
540                                 continue;
541                         }
542                         sam_pwent.gid = pwd->pw_gid;
543                 }
544
545                 /* Fill in sam_pwent structure */
546                 sam_pwent.user_rid = pdb_uid_to_user_rid (sam_pwent.uid);
547                 sam_pwent.group_rid = pdb_gid_to_group_rid (sam_pwent.gid);
548                 /* TODO: set also full_name, home_dir, dir_drive, logon_script, profile_path, ecc...
549                  * when defaults will be available (after passdb redesign)
550                  * let them blank just now they are not used anyway
551                  */
552                                          
553                  /* Now ADD the entry */
554                 if (!(pdb_add_sam_account (&sam_pwent)))
555                 {
556                         fprintf (stderr, "Unable to add user entry!\n");
557                         continue;
558                 }
559                 printf ("%s imported!\n", user_name);
560                 good++;
561         }
562         printf ("%d lines read.\n%d entryes imported\n", line, good);
563         
564         return 0;
565 }
566
567 /*********************************************************
568  Start here.
569 **********************************************************/
570 int main (int argc, char **argv)
571 {
572         int ch;
573         static pstring servicesf = CONFIGFILE;
574         BOOL list_users = FALSE;
575         BOOL verbose = FALSE;
576         BOOL spstyle = FALSE;
577         BOOL setparms = FALSE;
578         BOOL machine = FALSE;
579         BOOL add_user = FALSE;
580         BOOL delete_user = FALSE;
581         BOOL import = FALSE;
582         char *user_name = NULL;
583         char *full_name = NULL;
584         char *home_dir = NULL;
585         char *home_drive = NULL;
586         char *logon_script = NULL;
587         char *profile_path = NULL;
588         char *smbpasswd = NULL;
589
590         TimeInit();
591         
592         setup_logging("tdbedit", True);
593
594         charset_initialise();
595
596         if (argc < 2)
597
598         {
599                 usage();
600                 return 0;
601         }
602         
603         if(!initialize_password_db(True)) {
604                 fprintf(stderr, "Can't setup password database vectors.\n");
605                 exit(1);
606         }
607         
608         if (!lp_load(servicesf,True,False,False)) {
609                 fprintf(stderr, "Can't load %s - run testparm to debug it\n", 
610                         servicesf);
611                 exit(1);
612         }
613         
614         while ((ch = getopt(argc, argv, "ad:f:h:i:lmp:s:u:vwx")) != EOF) {
615                 switch(ch) {
616                 case 'a':
617                         add_user = TRUE;
618                         break;
619                 case 'm':
620                         machine = TRUE;
621                         break;
622                 case 'l':
623                         list_users = TRUE;
624                         break;
625                 case 'v':
626                         verbose = TRUE;
627                         break;
628                 case 'w':
629                         spstyle = TRUE;
630                         break;
631                 case 'u':
632                         user_name = optarg;
633                         break;
634                 case 'f':
635                         setparms = TRUE;
636                         full_name = optarg;
637                         break;
638                 case 'h':
639                         setparms = TRUE;
640                         home_dir = optarg;
641                         break;
642                 case 'd':
643                         setparms = TRUE;
644                         home_drive = optarg;
645                         break;
646                 case 's':
647                         setparms = TRUE;
648                         logon_script = optarg;
649                         break;
650                 case 'p':
651                         setparms = TRUE;
652                         profile_path = optarg;
653                         break;
654                 case 'x':
655                         delete_user = TRUE;
656                         break;
657                 case 'i':
658                         import = TRUE;
659                         smbpasswd = optarg;
660                         break;
661                 default:
662                         usage();
663                 }
664         }
665         if (((add_user?1:0) + (delete_user?1:0) + (list_users?1:0) + (import?1:0) + (setparms?1:0)) > 1)
666         {
667                 fprintf (stderr, "Incompatible options on command line!\n");
668                 usage();
669                 exit(1);
670         }
671
672         if (add_user) 
673         {
674                 if (!user_name)
675                 {
676                         fprintf (stderr, "Username not specified! (use -u option)\n");
677                         return -1;
678                 }
679                 if (machine) return new_machine (user_name);
680                 else return new_user (user_name, full_name, home_dir, home_drive, logon_script, profile_path);
681         }
682
683         if (delete_user)
684         {
685                 if (!user_name)
686                 {
687                         fprintf (stderr, "Username not specified! (use -u option)\n");
688                         return -1;
689                 }
690                 if (machine) return delete_machine_entry (user_name);
691                 else return delete_user_entry (user_name);
692         }
693         
694         if (user_name) 
695         {
696                 if (setparms) set_user_info (   user_name,
697                                                 full_name,
698                                                 home_dir,
699                                                 home_drive,
700                                                 logon_script,
701                                                 profile_path);
702                                                 
703                 else return print_user_info (user_name, verbose, spstyle);
704                 
705                 return 0;
706         }
707
708         
709         if (list_users) 
710                 return print_users_list (verbose, spstyle);
711         
712         if (import) 
713                 return import_users (smbpasswd); 
714         
715         usage();
716
717         return 0;
718 }
719
720