This is the 'multiple pdb backends' patch from ctrlsoft, aka Jelmer Vernooij
[kai/samba.git] / source3 / utils / pdbedit.c
1 /* 
2    Unix SMB/CIFS implementation.
3    passdb editing frontend
4    
5    Copyright (C) Simo Sorce      2000
6    Copyright (C) Andrew Bartlett 2001   
7    Copyright (C) Jelmer Vernooij 2002
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 extern pstring global_myname;
27 extern BOOL AllowDebugChange;
28
29 /*********************************************************
30  Add all currently available users to another db
31  ********************************************************/
32
33 int export_database (struct pdb_context *in, char *db){
34         struct pdb_context *context;
35         SAM_ACCOUNT *user = NULL;
36
37         if(!NT_STATUS_IS_OK(make_pdb_context_name(&context, db))){
38                 fprintf(stderr, "Can't initialize %s.\n", db);
39                 return 1;
40         }
41
42         if(!in->pdb_setsampwent(in, 0)){
43                 fprintf(stderr, "Can't sampwent!\n");
44                 return 1;
45         }
46
47         if(!NT_STATUS_IS_OK(pdb_init_sam(&user))){
48                 fprintf(stderr, "Can't initialize new SAM_ACCOUNT!\n");
49                 return 1;
50         }
51
52         while(in->pdb_getsampwent(in,user)){
53                 context->pdb_add_sam_account(context,user);
54                 if(!NT_STATUS_IS_OK(pdb_reset_sam(user))){
55                         fprintf(stderr, "Can't reset SAM_ACCOUNT!\n");
56                         return 1;
57                 }
58         }
59
60         in->pdb_endsampwent(in);
61
62         return 0;
63 }
64
65 /*********************************************************
66  Print info from sam structure
67 **********************************************************/
68
69 static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdstyle)
70 {
71         uid_t uid;
72         gid_t gid;
73
74         /* TODO: chaeck if entry is a user or a workstation */
75         if (!sam_pwent) return -1;
76         
77         if (verbosity) {
78                 printf ("username:       %s\n",  pdb_get_username(sam_pwent));
79                 if (IS_SAM_UNIX_USER(sam_pwent)) {
80                         uid = pdb_get_uid(sam_pwent);
81                         gid = pdb_get_gid(sam_pwent);
82                         printf ("user ID/Group:  %d/%d\n", uid, gid);
83                 }
84                 printf ("user RID/GRID:  %u/%u\n", (unsigned int)pdb_get_user_rid(sam_pwent),
85                         (unsigned int)pdb_get_group_rid(sam_pwent));
86                 printf ("Full Name:      %s\n", pdb_get_fullname(sam_pwent));
87                 printf ("Home Directory: %s\n", pdb_get_homedir(sam_pwent));
88                 printf ("HomeDir Drive:  %s\n", pdb_get_dirdrive(sam_pwent));
89                 printf ("Logon Script:   %s\n", pdb_get_logon_script(sam_pwent));
90                 printf ("Profile Path:   %s\n", pdb_get_profile_path(sam_pwent));
91         } else if (smbpwdstyle) {
92                 if (IS_SAM_UNIX_USER(sam_pwent)) {
93                         char lm_passwd[33];
94                         char nt_passwd[33];
95
96                         uid = pdb_get_uid(sam_pwent);
97                         pdb_sethexpwd(lm_passwd, 
98                                       pdb_get_lanman_passwd(sam_pwent), 
99                                       pdb_get_acct_ctrl(sam_pwent));
100                         pdb_sethexpwd(nt_passwd, 
101                                       pdb_get_nt_passwd(sam_pwent), 
102                                       pdb_get_acct_ctrl(sam_pwent));
103                         
104                         printf("%s:%d:%s:%s:%s:LCT-%08X:\n",
105                                pdb_get_username(sam_pwent),
106                                uid,
107                                lm_passwd,
108                                nt_passwd,
109                                pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN),
110                                (uint32)pdb_get_pass_last_set_time(sam_pwent));
111                 } else {
112                         fprintf(stderr, "Can't output in smbpasswd format, no uid on this record.\n");
113                 }
114         } else {
115                 if (IS_SAM_UNIX_USER(sam_pwent)) {
116                         printf ("%s:%d:%s\n", pdb_get_username(sam_pwent), pdb_get_uid(sam_pwent), 
117                                 pdb_get_fullname(sam_pwent));
118                 } else {        
119                         printf ("%s:(null):%s\n", pdb_get_username(sam_pwent), pdb_get_fullname(sam_pwent));
120                 }
121         }
122
123         return 0;       
124 }
125
126 /*********************************************************
127  Get an Print User Info
128 **********************************************************/
129
130 static int print_user_info (struct pdb_context *in, char *username, BOOL verbosity, BOOL smbpwdstyle)
131 {
132         SAM_ACCOUNT *sam_pwent=NULL;
133         BOOL ret;
134         
135         if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pwent))) {
136                 return -1;
137         }
138         
139         ret = in->pdb_getsampwnam (in, sam_pwent, username);
140
141         if (ret==False) {
142                 fprintf (stderr, "Username not found!\n");
143                 pdb_free_sam(&sam_pwent);
144                 return -1;
145         }
146         
147         ret=print_sam_info (sam_pwent, verbosity, smbpwdstyle);
148         pdb_free_sam(&sam_pwent);
149         
150         return ret;
151 }
152         
153 /*********************************************************
154  List Users
155 **********************************************************/
156 static int print_users_list (struct pdb_context *in, BOOL verbosity, BOOL smbpwdstyle)
157 {
158         SAM_ACCOUNT *sam_pwent=NULL;
159         BOOL check, ret;
160         
161         errno = 0; /* testing --simo */
162         check = in->pdb_setsampwent(in, False);
163         if (check && errno == ENOENT) {
164                 fprintf (stderr,"Password database not found!\n");
165                 exit(1);
166         }
167
168         check = True;
169         if (!(NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent)))) return 1;
170
171         while (check && (ret = in->pdb_getsampwent (in, sam_pwent))) {
172                 if (verbosity)
173                         printf ("---------------\n");
174                 print_sam_info (sam_pwent, verbosity, smbpwdstyle);
175                 pdb_free_sam(&sam_pwent);
176                 check = NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent));
177         }
178         if (check) pdb_free_sam(&sam_pwent);
179         
180         in->pdb_endsampwent(in);
181         return 0;
182 }
183
184 /*********************************************************
185  Set User Info
186 **********************************************************/
187
188 static int set_user_info (struct pdb_context *in, char *username, char *fullname, char *homedir, char *drive, char *script, char *profile)
189 {
190         SAM_ACCOUNT *sam_pwent=NULL;
191         BOOL ret;
192         
193         pdb_init_sam(&sam_pwent);
194         
195         ret = in->pdb_getsampwnam (in, sam_pwent, username);
196         if (ret==False) {
197                 fprintf (stderr, "Username not found!\n");
198                 pdb_free_sam(&sam_pwent);
199                 return -1;
200         }
201         
202         if (fullname)
203                 pdb_set_fullname(sam_pwent, fullname);
204         if (homedir)
205                 pdb_set_homedir(sam_pwent, homedir, True);
206         if (drive)
207                 pdb_set_dir_drive(sam_pwent,drive, True);
208         if (script)
209                 pdb_set_logon_script(sam_pwent, script, True);
210         if (profile)
211                 pdb_set_profile_path (sam_pwent, profile, True);
212         
213         if (in->pdb_update_sam_account (in, sam_pwent))
214                 print_user_info (in, username, True, False);
215         else {
216                 fprintf (stderr, "Unable to modify entry!\n");
217                 pdb_free_sam(&sam_pwent);
218                 return -1;
219         }
220         pdb_free_sam(&sam_pwent);
221         return 0;
222 }
223
224 /*********************************************************
225  Add New User
226 **********************************************************/
227 static int new_user (struct pdb_context *in, char *username, char *fullname, char *homedir, char *drive, char *script, char *profile)
228 {
229         SAM_ACCOUNT *sam_pwent=NULL;
230         struct passwd  *pwd = NULL;
231         char *password1, *password2;
232         
233         ZERO_STRUCT(sam_pwent);
234
235         if ((pwd = getpwnam_alloc(username))) {
236                 pdb_init_sam_pw (&sam_pwent, pwd);
237                 passwd_free(&pwd);
238         } else {
239                 fprintf (stderr, "WARNING: user %s does not exist in system passwd\n", username);
240                 pdb_init_sam(&sam_pwent);
241                 if (!pdb_set_username(sam_pwent, username)) {
242                         return False;
243                 }
244         }
245
246         password1 = getpass("new password:");
247         password2 = getpass("retype new password:");
248         if (strcmp (password1, password2)) {
249                  fprintf (stderr, "Passwords does not match!\n");
250                  pdb_free_sam (&sam_pwent);
251                  return -1;
252         }
253
254         pdb_set_plaintext_passwd(sam_pwent, password1);
255
256         if (fullname)
257                 pdb_set_fullname(sam_pwent, fullname);
258         if (homedir)
259                 pdb_set_homedir (sam_pwent, homedir, True);
260         if (drive)
261                 pdb_set_dir_drive (sam_pwent, drive, True);
262         if (script)
263                 pdb_set_logon_script(sam_pwent, script, True);
264         if (profile)
265                 pdb_set_profile_path (sam_pwent, profile, True);
266         
267         pdb_set_acct_ctrl (sam_pwent, ACB_NORMAL);
268         
269         if (in->pdb_add_sam_account (in, sam_pwent)) { 
270                 print_user_info (in, username, True, False);
271         } else {
272                 fprintf (stderr, "Unable to add user! (does it alredy exist?)\n");
273                 pdb_free_sam (&sam_pwent);
274                 return -1;
275         }
276         pdb_free_sam (&sam_pwent);
277         return 0;
278 }
279
280 /*********************************************************
281  Add New Machine
282 **********************************************************/
283
284 static int new_machine (struct pdb_context *in, char *machinename)
285 {
286         SAM_ACCOUNT *sam_pwent=NULL;
287         char name[16];
288         char *password = NULL;
289         
290         if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pwent))) {
291                 return -1;
292         }
293
294         if (machinename[strlen (machinename) -1] == '$')
295                 machinename[strlen (machinename) -1] = '\0';
296         
297         safe_strcpy (name, machinename, 16);
298         safe_strcat (name, "$", 16);
299         
300         string_set (&password, machinename);
301         strlower_m(password);
302         
303         pdb_set_plaintext_passwd (sam_pwent, password);
304
305         pdb_set_username (sam_pwent, name);
306         
307         pdb_set_acct_ctrl (sam_pwent, ACB_WSTRUST);
308         
309         pdb_set_group_rid(sam_pwent, DOMAIN_GROUP_RID_COMPUTERS);
310         
311         if (in->pdb_add_sam_account (in, sam_pwent)) {
312                 print_user_info (in, name, True, False);
313         } else {
314                 fprintf (stderr, "Unable to add machine! (does it already exist?)\n");
315                 pdb_free_sam (&sam_pwent);
316                 return -1;
317         }
318         pdb_free_sam (&sam_pwent);
319         return 0;
320 }
321
322 /*********************************************************
323  Delete user entry
324 **********************************************************/
325
326 static int delete_user_entry (struct pdb_context *in, char *username)
327 {
328         SAM_ACCOUNT *samaccount = NULL;
329
330         if (!NT_STATUS_IS_OK(pdb_init_sam (&samaccount))) {
331                 return -1;
332         }
333
334         if (!in->pdb_getsampwnam(in, samaccount, username)) {
335                 fprintf (stderr, "user %s does not exist in the passdb\n", username);
336                 return -1;
337         }
338
339         return in->pdb_delete_sam_account (in, samaccount);
340 }
341
342 /*********************************************************
343  Delete machine entry
344 **********************************************************/
345
346 static int delete_machine_entry (struct pdb_context *in, char *machinename)
347 {
348         char name[16];
349         SAM_ACCOUNT *samaccount = NULL;
350         
351         safe_strcpy (name, machinename, 16);
352         if (name[strlen(name)] != '$')
353                 safe_strcat (name, "$", 16);
354
355         if (!NT_STATUS_IS_OK(pdb_init_sam (&samaccount))) {
356                 return -1;
357         }
358
359         if (!in->pdb_getsampwnam(in, samaccount, name)) {
360                 fprintf (stderr, "user %s does not exist in the passdb\n", name);
361                 return -1;
362         }
363
364         return in->pdb_delete_sam_account (in, samaccount);
365 }
366
367 /*********************************************************
368  Start here.
369 **********************************************************/
370
371 int main (int argc, char **argv)
372 {
373         struct pdb_context *in;
374         BOOL list_users = False;
375         BOOL verbose = False;
376         BOOL spstyle = False;
377         BOOL setparms = False;
378         BOOL machine = False;
379         BOOL add_user = False;
380         BOOL delete_user = False;
381         BOOL import = False;
382         int opt;
383         char *full_name = NULL;
384         char *user_name = NULL;
385         char *home_dir = NULL;
386         char *home_drive = NULL;
387         char *backend_in = NULL;
388         char *backend_out = NULL;
389         char *logon_script = NULL;
390         char *profile_path = NULL;
391         poptContext pc;
392         struct poptOption long_options[] = {
393                 POPT_AUTOHELP
394                 {"list",        'l',POPT_ARG_VAL, &list_users, 1, "list all users", NULL},
395                 {"verbose",     'v',POPT_ARG_VAL, &verbose, 1, "be verbose", NULL },
396                 {"smbpasswd-style",     'w',POPT_ARG_VAL, &spstyle, 1, "give output in smbpasswd style", NULL},
397                 {"user",        'u',POPT_ARG_STRING,&user_name, 0, "use username", "USER" },
398                 {"fullname",    'f',POPT_ARG_STRING,&full_name, 0, "set full name", NULL},
399                 {"homedir",     'h',POPT_ARG_STRING,&home_dir, 0, "set home directory", NULL},
400                 {"drive",       'd',POPT_ARG_STRING,&home_drive, 0, "set home drive", NULL},
401                 {"script",      's',POPT_ARG_STRING,&logon_script, 0, "set logon script", NULL},
402                 {"profile",     'p',POPT_ARG_STRING,&profile_path, 0, "set profile path", NULL},
403                 {"create",      'a',POPT_ARG_VAL,&add_user, 1, "create user", NULL},
404                 {"machine",     'm',POPT_ARG_VAL,&machine, 1,"account is a machine account",NULL},
405                 {"delete",      'x',POPT_ARG_VAL,&delete_user,1,"delete user",NULL},
406                 {"import",      'i',POPT_ARG_STRING,&backend_in,0,"use different passdb backend",NULL},
407                 {"export",      'e',POPT_ARG_STRING,&backend_out,0,"export user accounts to backend", NULL},
408                 {"debuglevel",'D',POPT_ARG_INT,&DEBUGLEVEL,0,"set debuglevel",NULL},
409                 {0,0,0,0}
410         };
411         
412         DEBUGLEVEL = 1;
413         setup_logging("pdbedit", True);
414         AllowDebugChange = False;
415         
416         if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
417                 fprintf(stderr, "Can't load %s - run testparm to debug it\n", 
418                         dyn_CONFIGFILE);
419                 exit(1);
420         }
421
422         backend_in = lp_passdb_backend();
423
424         pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
425                                                 POPT_CONTEXT_KEEP_FIRST);
426
427         while((opt = poptGetNextOpt(pc)) != -1);
428
429         setparms = (full_name || home_dir || home_drive || logon_script || profile_path);
430
431         if (((add_user?1:0) + (delete_user?1:0) + (list_users?1:0) + (import?1:0) + (setparms?1:0)) + (backend_out?1:0) > 1) {
432                 fprintf (stderr, "Incompatible options on command line!\n");
433                 exit(1);
434         }
435         
436
437         if(!NT_STATUS_IS_OK(make_pdb_context_name(&in, backend_in))){
438                 fprintf(stderr, "Can't initialize %s.\n", backend_in);
439                 return 1;
440         }
441
442         if (add_user) {
443                 if (!user_name) {
444                         fprintf (stderr, "Username not specified! (use -u option)\n");
445                         return -1;
446                 }
447                 if (machine)
448                         return new_machine (in, user_name);
449                 else
450                         return new_user (in, user_name, full_name, home_dir, home_drive, logon_script, profile_path);
451         }
452
453         if (delete_user) {
454                 if (!user_name) {
455                         fprintf (stderr, "Username not specified! (use -u option)\n");
456                         return -1;
457                 }
458                 if (machine)
459                         return delete_machine_entry (in, user_name);
460                 else
461                         return delete_user_entry (in, user_name);
462         }
463         
464         if (user_name) {
465                 if (setparms)
466                         return set_user_info (in,       user_name, full_name,
467                                                 home_dir,
468                                                 home_drive,
469                                                 logon_script,
470                                                 profile_path);
471                 else
472                         return print_user_info (in, user_name, verbose, spstyle);
473         }
474
475         if (list_users) 
476                 return print_users_list (in, verbose, spstyle);
477
478         if (backend_out)
479                 return export_database(in, backend_out);
480         
481         poptPrintHelp(pc, stderr, 0);
482         
483         return 1;
484 }