s3:utils: Avoid integer overflow (CID 1035488)
[samba.git] / source3 / utils / pdbedit.c
1 /*
2    Unix SMB/CIFS implementation.
3    passdb editing frontend
4
5    Copyright (C) Simo Sorce      2000-2009
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 3 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, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "lib/cmdline/cmdline.h"
25 #include "../librpc/gen_ndr/samr.h"
26 #include "../libcli/security/security.h"
27 #include "passdb.h"
28 #include "cmdline_contexts.h"
29 #include "passwd_proto.h"
30 #include "lib/util/smb_strtox.h"
31 #include "lib/param/param.h"
32
33 #define BIT_BACKEND     0x00000004
34 #define BIT_VERBOSE     0x00000008
35 #define BIT_SPSTYLE     0x00000010
36 #define BIT_CAN_CHANGE  0x00000020
37 #define BIT_MUST_CHANGE 0x00000040
38 #define BIT_USERSIDS    0x00000080
39 #define BIT_FULLNAME    0x00000100
40 #define BIT_HOMEDIR     0x00000200
41 #define BIT_HDIRDRIVE   0x00000400
42 #define BIT_LOGSCRIPT   0x00000800
43 #define BIT_PROFILE     0x00001000
44 #define BIT_MACHINE     0x00002000
45 #define BIT_USERDOMAIN  0x00004000
46 #define BIT_USER        0x00008000
47 #define BIT_LIST        0x00010000
48 #define BIT_MODIFY      0x00020000
49 #define BIT_CREATE      0x00040000
50 #define BIT_DELETE      0x00080000
51 #define BIT_ACCPOLICY   0x00100000
52 #define BIT_ACCPOLVAL   0x00200000
53 #define BIT_ACCTCTRL    0x00400000
54 #define BIT_RESERV_7    0x00800000
55 #define BIT_IMPORT      0x01000000
56 #define BIT_EXPORT      0x02000000
57 #define BIT_FIX_INIT    0x04000000
58 #define BIT_BADPWRESET  0x08000000
59 #define BIT_LOGONHOURS  0x10000000
60 #define BIT_KICKOFFTIME 0x20000000
61 #define BIT_DESCRIPTION 0x40000000
62 #define BIT_PWSETNTHASH 0x80000000
63
64 #define MASK_ALWAYS_GOOD        0x0000001F
65 #define MASK_USER_GOOD          0xE0405FE0
66
67 static int get_sid_from_cli_string(struct dom_sid *sid, const char *str_sid)
68 {
69         uint32_t rid;
70
71         if (!string_to_sid(sid, str_sid)) {
72                 /* not a complete sid, may be a RID,
73                  * try building a SID */
74
75                 if (sscanf(str_sid, "%u", &rid) != 1) {
76                         fprintf(stderr, "Error passed string is not "
77                                         "a complete SID or RID!\n");
78                         return -1;
79                 }
80                 sid_compose(sid, get_global_sam_sid(), rid);
81         }
82
83         return 0;
84 }
85
86 /*********************************************************
87  Add all currently available users to another db
88  ********************************************************/
89
90 static int export_database (struct pdb_methods *in,
91                             struct pdb_methods *out,
92                             const char *username)
93 {
94         NTSTATUS status;
95         struct pdb_search *u_search;
96         struct samr_displayentry userentry;
97
98         DEBUG(3, ("export_database: username=\"%s\"\n", username ? username : "(NULL)"));
99
100         u_search = pdb_search_init(talloc_tos(), PDB_USER_SEARCH);
101         if (u_search == NULL) {
102                 DEBUG(0, ("pdb_search_init failed\n"));
103                 return 1;
104         }
105
106         if (!in->search_users(in, u_search, 0)) {
107                 DEBUG(0, ("Could not start searching users\n"));
108                 TALLOC_FREE(u_search);
109                 return 1;
110         }
111
112         while (u_search->next_entry(u_search, &userentry)) {
113                 struct samu *user;
114                 struct samu *account;
115                 struct dom_sid user_sid;
116
117                 DEBUG(4, ("Processing account %s\n", userentry.account_name));
118
119                 if ((username != NULL)
120                     && (strcmp(username, userentry.account_name) != 0)) {
121                         /*
122                          * ignore unwanted users
123                          */
124                         continue;
125                 }
126
127                 user = samu_new(talloc_tos());
128                 if (user == NULL) {
129                         DEBUG(0, ("talloc failed\n"));
130                         break;
131                 }
132
133                 sid_compose(&user_sid, get_global_sam_sid(), userentry.rid);
134
135                 status = in->getsampwsid(in, user, &user_sid);
136
137                 if (!NT_STATUS_IS_OK(status)) {
138                         DEBUG(2, ("getsampwsid failed: %s\n",
139                                   nt_errstr(status)));
140                         TALLOC_FREE(user);
141                         continue;
142                 }
143
144                 account = samu_new(NULL);
145                 if (account == NULL) {
146                         fprintf(stderr, "export_database: Memory allocation "
147                                 "failure!\n");
148                         TALLOC_FREE( user );
149                         TALLOC_FREE(u_search);
150                         return 1;
151                 }
152
153                 printf("Importing account for %s...", user->username);
154                 status = out->getsampwnam(out, account, user->username);
155
156                 if (NT_STATUS_IS_OK(status)) {
157                         status = out->update_sam_account( out, user );
158                 } else {
159                         status = out->add_sam_account(out, user);
160                 }
161
162                 if ( NT_STATUS_IS_OK(status) ) {
163                         printf( "ok\n");
164                 } else {
165                         printf( "failed\n");
166                 }
167
168                 TALLOC_FREE( account );
169                 TALLOC_FREE( user );
170         }
171
172         TALLOC_FREE(u_search);
173
174         return 0;
175 }
176
177 /*********************************************************
178  Add all currently available group mappings to another db
179  ********************************************************/
180
181 static int export_groups (struct pdb_methods *in, struct pdb_methods *out)
182 {
183         GROUP_MAP **maps = NULL;
184         size_t i, entries = 0;
185         NTSTATUS status;
186
187         status = in->enum_group_mapping(in, get_global_sam_sid(),
188                         SID_NAME_DOM_GRP, &maps, &entries, False);
189
190         if ( NT_STATUS_IS_ERR(status) ) {
191                 fprintf(stderr, "Unable to enumerate group map entries.\n");
192                 return 1;
193         }
194
195         for (i=0; i<entries; i++) {
196                 out->add_group_mapping_entry(out, maps[i]);
197         }
198
199         TALLOC_FREE(maps);
200
201         return 0;
202 }
203
204 /*********************************************************
205  Reset account policies to their default values and remove marker
206  ********************************************************/
207
208 static int reinit_account_policies (void)
209 {
210         int i;
211
212         for (i=1; decode_account_policy_name(i) != NULL; i++) {
213                 uint32_t policy_value;
214                 if (!account_policy_get_default(i, &policy_value)) {
215                         fprintf(stderr, "Can't get default account policy\n");
216                         return -1;
217                 }
218                 if (!account_policy_set(i, policy_value)) {
219                         fprintf(stderr, "Can't set account policy in tdb\n");
220                         return -1;
221                 }
222         }
223
224         return 0;
225 }
226
227
228 /*********************************************************
229  Add all currently available account policy from tdb to one backend
230  ********************************************************/
231
232 static int export_account_policies (struct pdb_methods *in, struct pdb_methods *out)
233 {
234         int i;
235
236         for ( i=1; decode_account_policy_name(i) != NULL; i++ ) {
237                 uint32_t policy_value;
238                 NTSTATUS status;
239
240                 status = in->get_account_policy(in, i, &policy_value);
241
242                 if ( NT_STATUS_IS_ERR(status) ) {
243                         fprintf(stderr, "Unable to get account policy from %s\n", in->name);
244                         return -1;
245                 }
246
247                 status = out->set_account_policy(out, i, policy_value);
248
249                 if ( NT_STATUS_IS_ERR(status) ) {
250                         fprintf(stderr, "Unable to migrate account policy to %s\n", out->name);
251                         return -1;
252                 }
253         }
254
255         return 0;
256 }
257
258
259 /*********************************************************
260  Print info from sam structure
261 **********************************************************/
262
263 static int print_sam_info (struct samu *sam_pwent, bool verbosity, bool smbpwdstyle)
264 {
265         uid_t uid;
266         time_t tmp;
267
268         /* TODO: check if entry is a user or a workstation */
269         if (!sam_pwent) return -1;
270
271         if (verbosity) {
272                 char temp[44];
273                 const uint8_t *hours;
274                 struct dom_sid_buf buf;
275
276                 printf ("Unix username:        %s\n", pdb_get_username(sam_pwent));
277                 printf ("NT username:          %s\n", pdb_get_nt_username(sam_pwent));
278                 printf ("Account Flags:        %s\n", pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent), NEW_PW_FORMAT_SPACE_PADDED_LEN));
279                 printf ("User SID:             %s\n",
280                         dom_sid_str_buf(pdb_get_user_sid(sam_pwent), &buf));
281                 printf ("Primary Group SID:    %s\n",
282                         dom_sid_str_buf(pdb_get_group_sid(sam_pwent), &buf));
283                 printf ("Full Name:            %s\n", pdb_get_fullname(sam_pwent));
284                 printf ("Home Directory:       %s\n", pdb_get_homedir(sam_pwent));
285                 printf ("HomeDir Drive:        %s\n", pdb_get_dir_drive(sam_pwent));
286                 printf ("Logon Script:         %s\n", pdb_get_logon_script(sam_pwent));
287                 printf ("Profile Path:         %s\n", pdb_get_profile_path(sam_pwent));
288                 printf ("Domain:               %s\n", pdb_get_domain(sam_pwent));
289                 printf ("Account desc:         %s\n", pdb_get_acct_desc(sam_pwent));
290                 printf ("Workstations:         %s\n", pdb_get_workstations(sam_pwent));
291                 printf ("Munged dial:          %s\n", pdb_get_munged_dial(sam_pwent));
292
293                 tmp = pdb_get_logon_time(sam_pwent);
294                 printf ("Logon time:           %s\n",
295                                 tmp ? http_timestring(talloc_tos(), tmp) : "0");
296
297                 tmp = pdb_get_logoff_time(sam_pwent);
298                 printf ("Logoff time:          %s\n",
299                                 tmp ? http_timestring(talloc_tos(), tmp) : "0");
300
301                 tmp = pdb_get_kickoff_time(sam_pwent);
302                 printf ("Kickoff time:         %s\n",
303                                 tmp ? http_timestring(talloc_tos(), tmp) : "0");
304
305                 tmp = pdb_get_pass_last_set_time(sam_pwent);
306                 printf ("Password last set:    %s\n",
307                                 tmp ? http_timestring(talloc_tos(), tmp) : "0");
308
309                 tmp = pdb_get_pass_can_change_time(sam_pwent);
310                 printf ("Password can change:  %s\n",
311                                 tmp ? http_timestring(talloc_tos(), tmp) : "0");
312
313                 tmp = pdb_get_pass_must_change_time(sam_pwent);
314                 printf ("Password must change: %s\n",
315                                 tmp ? http_timestring(talloc_tos(), tmp) : "0");
316
317                 tmp = pdb_get_bad_password_time(sam_pwent);
318                 printf ("Last bad password   : %s\n",
319                                 tmp ? http_timestring(talloc_tos(), tmp) : "0");
320                 printf ("Bad password count  : %d\n",
321                         pdb_get_bad_password_count(sam_pwent));
322
323                 hours = pdb_get_hours(sam_pwent);
324                 pdb_sethexhours(temp, hours);
325                 printf ("Logon hours         : %s\n", temp);
326                 if (smbpwdstyle){
327                         pdb_sethexpwd(temp, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
328                         printf ("LM hash             : %s\n", temp);
329                         pdb_sethexpwd(temp, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
330                         printf ("NT hash             : %s\n", temp);
331                 }
332
333         } else if (smbpwdstyle) {
334                 char lm_passwd[33];
335                 char nt_passwd[33];
336
337                 uid = nametouid(pdb_get_username(sam_pwent));
338                 pdb_sethexpwd(lm_passwd, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
339                 pdb_sethexpwd(nt_passwd, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
340
341                 printf("%s:%lu:%s:%s:%s:LCT-%08X:\n",
342                        pdb_get_username(sam_pwent),
343                        (unsigned long)uid,
344                        lm_passwd,
345                        nt_passwd,
346                        pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN),
347                        (uint32_t)convert_time_t_to_uint32_t(pdb_get_pass_last_set_time(sam_pwent)));
348         } else {
349                 uid = nametouid(pdb_get_username(sam_pwent));
350                 printf ("%s:%lu:%s\n", pdb_get_username(sam_pwent), (unsigned long)uid,
351                         pdb_get_fullname(sam_pwent));
352         }
353
354         return 0;
355 }
356
357 /*********************************************************
358  Get an Print User Info
359 **********************************************************/
360
361 static int print_user_info(const char *username,
362                            bool verbosity, bool smbpwdstyle)
363 {
364         struct samu *sam_pwent = NULL;
365         bool bret;
366         int ret;
367
368         sam_pwent = samu_new(NULL);
369         if (!sam_pwent) {
370                 return -1;
371         }
372
373         bret = pdb_getsampwnam(sam_pwent, username);
374         if (!bret) {
375                 fprintf (stderr, "Username not found!\n");
376                 TALLOC_FREE(sam_pwent);
377                 return -1;
378         }
379
380         ret = print_sam_info(sam_pwent, verbosity, smbpwdstyle);
381
382         TALLOC_FREE(sam_pwent);
383         return ret;
384 }
385
386 /*********************************************************
387  List Users
388 **********************************************************/
389 static int print_users_list(bool verbosity, bool smbpwdstyle)
390 {
391         struct pdb_search *u_search;
392         struct samr_displayentry userentry;
393         struct samu *sam_pwent;
394         TALLOC_CTX *tosctx;
395         struct dom_sid user_sid;
396         bool bret;
397         int ret;
398
399         tosctx = talloc_tos();
400         if (!tosctx) {
401                 DEBUG(0, ("talloc failed\n"));
402                 return 1;
403         }
404
405         u_search = pdb_search_users(tosctx, 0);
406         if (!u_search) {
407                 DEBUG(0, ("User Search failed!\n"));
408                 ret = 1;
409                 goto done;
410         }
411
412         while (u_search->next_entry(u_search, &userentry)) {
413
414                 sam_pwent = samu_new(tosctx);
415                 if (sam_pwent == NULL) {
416                         DEBUG(0, ("talloc failed\n"));
417                         ret = 1;
418                         goto done;
419                 }
420
421                 sid_compose(&user_sid, get_global_sam_sid(), userentry.rid);
422
423                 bret = pdb_getsampwsid(sam_pwent, &user_sid);
424                 if (!bret) {
425                         DEBUG(2, ("getsampwsid failed\n"));
426                         TALLOC_FREE(sam_pwent);
427                         continue;
428                 }
429
430                 if (verbosity) {
431                         printf ("---------------\n");
432                 }
433                 print_sam_info(sam_pwent, verbosity, smbpwdstyle);
434                 TALLOC_FREE(sam_pwent);
435         }
436
437         ret = 0;
438
439 done:
440         TALLOC_FREE(tosctx);
441         return ret;
442 }
443
444 /*********************************************************
445  Fix a list of Users for uninitialised passwords
446 **********************************************************/
447 static int fix_users_list(void)
448 {
449         struct pdb_search *u_search;
450         struct samr_displayentry userentry;
451         struct samu *sam_pwent;
452         TALLOC_CTX *tosctx;
453         struct dom_sid user_sid;
454         NTSTATUS status;
455         bool bret;
456         int ret;
457
458         tosctx = talloc_tos();
459         if (!tosctx) {
460                 fprintf(stderr, "Out of memory!\n");
461                 return 1;
462         }
463
464         u_search = pdb_search_users(tosctx, 0);
465         if (!u_search) {
466                 fprintf(stderr, "User Search failed!\n");
467                 ret = 1;
468                 goto done;
469         }
470
471         while (u_search->next_entry(u_search, &userentry)) {
472
473                 sam_pwent = samu_new(tosctx);
474                 if (sam_pwent == NULL) {
475                         fprintf(stderr, "Out of memory!\n");
476                         ret = 1;
477                         goto done;
478                 }
479
480                 sid_compose(&user_sid, get_global_sam_sid(), userentry.rid);
481
482                 bret = pdb_getsampwsid(sam_pwent, &user_sid);
483                 if (!bret) {
484                         DEBUG(2, ("getsampwsid failed\n"));
485                         TALLOC_FREE(sam_pwent);
486                         continue;
487                 }
488
489                 status = pdb_update_sam_account(sam_pwent);
490                 if (!NT_STATUS_IS_OK(status)) {
491                         printf("Update of user %s failed!\n",
492                                pdb_get_username(sam_pwent));
493                 }
494                 TALLOC_FREE(sam_pwent);
495         }
496
497         ret = 0;
498
499 done:
500         TALLOC_FREE(tosctx);
501         return ret;
502 }
503
504 /*********************************************************
505  Set User Info
506 **********************************************************/
507
508 static int set_user_info(const char *username, const char *fullname,
509                          const char *homedir, const char *acct_desc,
510                          const char *drive, const char *script,
511                          const char *profile, const char *account_control,
512                          const char *user_sid, const char *user_domain,
513                          const bool badpw, const bool hours,
514                          const char *kickoff_time, const char *str_hex_pwd)
515 {
516         bool updated_autolock = False, updated_badpw = False;
517         struct samu *sam_pwent;
518         uint8_t hours_array[MAX_HOURS_LEN];
519         uint32_t hours_len;
520         uint32_t acb_flags;
521         uint32_t not_settable;
522         uint32_t new_flags;
523         struct dom_sid u_sid;
524         bool ret;
525
526         sam_pwent = samu_new(NULL);
527         if (!sam_pwent) {
528                 return 1;
529         }
530
531         ret = pdb_getsampwnam(sam_pwent, username);
532         if (!ret) {
533                 fprintf (stderr, "Username not found!\n");
534                 TALLOC_FREE(sam_pwent);
535                 return -1;
536         }
537
538         if (hours) {
539                 hours_len = pdb_get_hours_len(sam_pwent);
540                 memset(hours_array, 0xff, hours_len);
541
542                 pdb_set_hours(sam_pwent, hours_array, hours_len, PDB_CHANGED);
543         }
544
545         if (!pdb_update_autolock_flag(sam_pwent, &updated_autolock)) {
546                 DEBUG(2,("pdb_update_autolock_flag failed.\n"));
547         }
548
549         if (!pdb_update_bad_password_count(sam_pwent, &updated_badpw)) {
550                 DEBUG(2,("pdb_update_bad_password_count failed.\n"));
551         }
552
553         if (fullname)
554                 pdb_set_fullname(sam_pwent, fullname, PDB_CHANGED);
555         if (acct_desc)
556                 pdb_set_acct_desc(sam_pwent, acct_desc, PDB_CHANGED);
557         if (homedir)
558                 pdb_set_homedir(sam_pwent, homedir, PDB_CHANGED);
559         if (drive)
560                 pdb_set_dir_drive(sam_pwent,drive, PDB_CHANGED);
561         if (script)
562                 pdb_set_logon_script(sam_pwent, script, PDB_CHANGED);
563         if (profile)
564                 pdb_set_profile_path (sam_pwent, profile, PDB_CHANGED);
565         if (user_domain)
566                 pdb_set_domain(sam_pwent, user_domain, PDB_CHANGED);
567
568         if (account_control) {
569                 not_settable = ~(ACB_DISABLED | ACB_HOMDIRREQ |
570                                  ACB_PWNOTREQ | ACB_PWNOEXP | ACB_AUTOLOCK);
571
572                 new_flags = pdb_decode_acct_ctrl(account_control);
573
574                 if (new_flags & not_settable) {
575                         fprintf(stderr, "Can only set [NDHLX] flags\n");
576                         TALLOC_FREE(sam_pwent);
577                         return -1;
578                 }
579
580                 acb_flags = pdb_get_acct_ctrl(sam_pwent);
581
582                 pdb_set_acct_ctrl(sam_pwent,
583                                   (acb_flags & not_settable) | new_flags,
584                                   PDB_CHANGED);
585         }
586         if (user_sid) {
587                 if (get_sid_from_cli_string(&u_sid, user_sid)) {
588                         fprintf(stderr, "Failed to parse SID\n");
589                         return -1;
590                 }
591                 pdb_set_user_sid(sam_pwent, &u_sid, PDB_CHANGED);
592         }
593
594         if (badpw) {
595                 pdb_set_bad_password_count(sam_pwent, 0, PDB_CHANGED);
596                 pdb_set_bad_password_time(sam_pwent, 0, PDB_CHANGED);
597         }
598
599         if (kickoff_time) {
600                 time_t value = get_time_t_max();
601
602                 if (strcmp(kickoff_time, "never") != 0) {
603                         int error = 0;
604                         uint32_t num;
605
606                         num = smb_strtoul(kickoff_time,
607                                           NULL,
608                                           10,
609                                           &error,
610                                           SMB_STR_FULL_STR_CONV);
611                         if (error != 0) {
612                                 fprintf(stderr, "Failed to parse kickoff time\n");
613                                 return -1;
614                         }
615
616                         value = convert_uint32_t_to_time_t(num);
617                 }
618
619                 pdb_set_kickoff_time(sam_pwent, value, PDB_CHANGED);
620         }
621         if (str_hex_pwd) {
622                 unsigned char  new_nt_p16[NT_HASH_LEN];
623                 if(strlen(str_hex_pwd) != (NT_HASH_LEN *2)){
624                         fprintf(stderr, "Invalid hash\n");
625                         return -1;
626                 }
627
628                 pdb_gethexpwd(str_hex_pwd, new_nt_p16);
629
630                 if (!pdb_set_nt_passwd (sam_pwent, new_nt_p16 , PDB_CHANGED)) {
631                         fprintf(stderr, "Failed to set password from nt-hash\n");
632                         return -1;
633                 }
634
635                 if (!pdb_set_pass_last_set_time (sam_pwent, time(NULL), PDB_CHANGED)){
636                         fprintf(stderr, "Failed to set last password set time\n");
637                         return -1;
638                 }
639                 if (!pdb_update_history(sam_pwent, new_nt_p16)){
640                         fprintf(stderr, "Failed to update password history\n");
641                         return -1;
642                 }
643         }
644
645         if (NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) {
646
647                 print_user_info(username, True, (str_hex_pwd != NULL ));
648         } else {
649                 fprintf (stderr, "Unable to modify entry!\n");
650                 TALLOC_FREE(sam_pwent);
651                 return -1;
652         }
653         TALLOC_FREE(sam_pwent);
654         return 0;
655 }
656
657 static int set_machine_info(const char *machinename,
658                             const char *account_control,
659                             const char *machine_sid)
660 {
661         struct samu *sam_pwent = NULL;
662         TALLOC_CTX *tosctx;
663         uint32_t acb_flags;
664         uint32_t not_settable;
665         uint32_t new_flags;
666         struct dom_sid m_sid;
667         char *name;
668         int len;
669         bool ret;
670
671         len = strlen(machinename);
672         if (len == 0) {
673                 fprintf(stderr, "No machine name given\n");
674                 return -1;
675         }
676
677         tosctx = talloc_tos();
678         if (!tosctx) {
679                 fprintf(stderr, "Out of memory!\n");
680                 return -1;
681         }
682
683         sam_pwent = samu_new(tosctx);
684         if (!sam_pwent) {
685                 return 1;
686         }
687
688         if (machinename[len-1] == '$') {
689                 name = talloc_strdup(sam_pwent, machinename);
690         } else {
691                 name = talloc_asprintf(sam_pwent, "%s$", machinename);
692         }
693         if (!name) {
694                 fprintf(stderr, "Out of memory!\n");
695                 TALLOC_FREE(sam_pwent);
696                 return -1;
697         }
698
699         if (!strlower_m(name)) {
700                 fprintf(stderr, "strlower_m %s failed\n", name);
701                 TALLOC_FREE(sam_pwent);
702                 return -1;
703         }
704
705         ret = pdb_getsampwnam(sam_pwent, name);
706         if (!ret) {
707                 fprintf (stderr, "Username not found!\n");
708                 TALLOC_FREE(sam_pwent);
709                 return -1;
710         }
711
712         if (account_control) {
713                 not_settable = ~(ACB_DISABLED);
714
715                 new_flags = pdb_decode_acct_ctrl(account_control);
716
717                 if (new_flags & not_settable) {
718                         fprintf(stderr, "Can only set [D] flags\n");
719                         TALLOC_FREE(sam_pwent);
720                         return -1;
721                 }
722
723                 acb_flags = pdb_get_acct_ctrl(sam_pwent);
724
725                 pdb_set_acct_ctrl(sam_pwent,
726                                   (acb_flags & not_settable) | new_flags,
727                                   PDB_CHANGED);
728         }
729         if (machine_sid) {
730                 if (get_sid_from_cli_string(&m_sid, machine_sid)) {
731                         fprintf(stderr, "Failed to parse SID\n");
732                         return -1;
733                 }
734                 pdb_set_user_sid(sam_pwent, &m_sid, PDB_CHANGED);
735         }
736
737         if (NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) {
738                 print_user_info(name, True, False);
739         } else {
740                 fprintf (stderr, "Unable to modify entry!\n");
741                 TALLOC_FREE(sam_pwent);
742                 return -1;
743         }
744         TALLOC_FREE(sam_pwent);
745         return 0;
746 }
747
748 /*********************************************************
749  Add New User
750 **********************************************************/
751 static int new_user(const char *username, const char *fullname,
752                     const char *homedir, const char *drive,
753                     const char *script, const char *profile,
754                     char *user_sid, bool stdin_get)
755 {
756         char *pwd1 = NULL, *pwd2 = NULL;
757         char *err = NULL, *msg = NULL;
758         struct samu *sam_pwent = NULL;
759         TALLOC_CTX *tosctx;
760         NTSTATUS status;
761         struct dom_sid u_sid;
762         int flags;
763         int ret = -1;
764
765         tosctx = talloc_tos();
766         if (!tosctx) {
767                 fprintf(stderr, "Out of memory!\n");
768                 return -1;
769         }
770
771         if (user_sid) {
772                 if (get_sid_from_cli_string(&u_sid, user_sid)) {
773                         fprintf(stderr, "Failed to parse SID\n");
774                         return -1;
775                 }
776         }
777
778         pwd1 = get_pass( "new password:", stdin_get);
779         if (pwd1 == NULL) {
780                 fprintf(stderr, "Failed to read passwords.\n");
781                 goto done;
782         }
783         pwd2 = get_pass( "retype new password:", stdin_get);
784         if (pwd2 == NULL) {
785                 fprintf(stderr, "Failed to read passwords.\n");
786                 goto done;
787         }
788         ret = strcmp(pwd1, pwd2);
789         if (ret != 0) {
790                 fprintf (stderr, "Passwords do not match!\n");
791                 goto done;
792         }
793
794         flags = LOCAL_ADD_USER | LOCAL_SET_PASSWORD;
795
796         status = local_password_change(username, flags, pwd1, &err, &msg);
797         if (!NT_STATUS_IS_OK(status)) {
798                 if (err) fprintf(stderr, "%s", err);
799                 ret = -1;
800                 goto done;
801         }
802
803         sam_pwent = samu_new(tosctx);
804         if (!sam_pwent) {
805                 fprintf(stderr, "Out of memory!\n");
806                 ret = -1;
807                 goto done;
808         }
809
810         if (!pdb_getsampwnam(sam_pwent, username)) {
811                 fprintf(stderr, "User %s not found!\n", username);
812                 ret = -1;
813                 goto done;
814         }
815
816         if (fullname)
817                 pdb_set_fullname(sam_pwent, fullname, PDB_CHANGED);
818         if (homedir)
819                 pdb_set_homedir(sam_pwent, homedir, PDB_CHANGED);
820         if (drive)
821                 pdb_set_dir_drive(sam_pwent, drive, PDB_CHANGED);
822         if (script)
823                 pdb_set_logon_script(sam_pwent, script, PDB_CHANGED);
824         if (profile)
825                 pdb_set_profile_path(sam_pwent, profile, PDB_CHANGED);
826         if (user_sid)
827                 pdb_set_user_sid(sam_pwent, &u_sid, PDB_CHANGED);
828
829         status = pdb_update_sam_account(sam_pwent);
830         if (!NT_STATUS_IS_OK(status)) {
831                 fprintf(stderr,
832                         "Failed to modify entry for user %s.!\n",
833                         username);
834                 ret = -1;
835                 goto done;
836         }
837
838         print_user_info(username, True, False);
839         ret = 0;
840
841 done:
842         if (pwd1) memset(pwd1, 0, strlen(pwd1));
843         if (pwd2) memset(pwd2, 0, strlen(pwd2));
844         SAFE_FREE(pwd1);
845         SAFE_FREE(pwd2);
846         SAFE_FREE(err);
847         SAFE_FREE(msg);
848         TALLOC_FREE(sam_pwent);
849         return ret;
850 }
851
852 /*********************************************************
853  Add New Machine
854 **********************************************************/
855
856 static int new_machine(const char *machinename, char *machine_sid)
857 {
858         char *err = NULL, *msg = NULL;
859         struct samu *sam_pwent = NULL;
860         TALLOC_CTX *tosctx;
861         NTSTATUS status;
862         struct dom_sid m_sid;
863         char *compatpwd;
864         char *name;
865         int flags;
866         int len;
867         int ret;
868
869         len = strlen(machinename);
870         if (len == 0) {
871                 fprintf(stderr, "No machine name given\n");
872                 return -1;
873         }
874
875         tosctx = talloc_tos();
876         if (!tosctx) {
877                 fprintf(stderr, "Out of memory!\n");
878                 return -1;
879         }
880
881         if (machine_sid) {
882                 if (get_sid_from_cli_string(&m_sid, machine_sid)) {
883                         fprintf(stderr, "Failed to parse SID\n");
884                         return -1;
885                 }
886         }
887
888         compatpwd = talloc_strdup(tosctx, machinename);
889         if (!compatpwd) {
890                 fprintf(stderr, "Out of memory!\n");
891                 return -1;
892         }
893
894         if (machinename[len-1] == '$') {
895                 name = talloc_strdup(tosctx, machinename);
896                 compatpwd[len-1] = '\0';
897         } else {
898                 name = talloc_asprintf(tosctx, "%s$", machinename);
899         }
900         if (!name) {
901                 fprintf(stderr, "Out of memory!\n");
902                 return -1;
903         }
904
905         if (!strlower_m(name)) {
906                 fprintf(stderr, "strlower_m %s failed\n", name);
907                 return -1;
908         }
909
910         flags = LOCAL_ADD_USER | LOCAL_TRUST_ACCOUNT | LOCAL_SET_PASSWORD;
911
912         status = local_password_change(name, flags, compatpwd, &err, &msg);
913
914         if (!NT_STATUS_IS_OK(status)) {
915                 if (err) fprintf(stderr, "%s", err);
916                 ret = -1;
917         }
918
919         sam_pwent = samu_new(tosctx);
920         if (!sam_pwent) {
921                 fprintf(stderr, "Out of memory!\n");
922                 ret = -1;
923                 goto done;
924         }
925
926         if (!pdb_getsampwnam(sam_pwent, name)) {
927                 fprintf(stderr, "Machine %s not found!\n", name);
928                 ret = -1;
929                 goto done;
930         }
931
932         if (machine_sid)
933                 pdb_set_user_sid(sam_pwent, &m_sid, PDB_CHANGED);
934
935         status = pdb_update_sam_account(sam_pwent);
936         if (!NT_STATUS_IS_OK(status)) {
937                 fprintf(stderr,
938                         "Failed to modify entry for %s.!\n", name);
939                 ret = -1;
940                 goto done;
941         }
942
943         print_user_info(name, True, False);
944         ret = 0;
945
946 done:
947         SAFE_FREE(err);
948         SAFE_FREE(msg);
949         TALLOC_FREE(sam_pwent);
950         return ret;
951 }
952
953 /*********************************************************
954  Delete user entry
955 **********************************************************/
956
957 static int delete_user_entry(const char *username)
958 {
959         struct samu *samaccount;
960
961         samaccount = samu_new(NULL);
962         if (!samaccount) {
963                 fprintf(stderr, "Out of memory!\n");
964                 return -1;
965         }
966
967         if (!pdb_getsampwnam(samaccount, username)) {
968                 fprintf (stderr,
969                          "user %s does not exist in the passdb\n", username);
970                 TALLOC_FREE(samaccount);
971                 return -1;
972         }
973
974         if (!NT_STATUS_IS_OK(pdb_delete_sam_account(samaccount))) {
975                 fprintf (stderr, "Unable to delete user %s\n", username);
976                 TALLOC_FREE(samaccount);
977                 return -1;
978         }
979
980         TALLOC_FREE(samaccount);
981         return 0;
982 }
983
984 /*********************************************************
985  Delete machine entry
986 **********************************************************/
987
988 static int delete_machine_entry(const char *machinename)
989 {
990         struct samu *samaccount = NULL;
991         const char *name;
992
993         if (strlen(machinename) == 0) {
994                 fprintf(stderr, "No machine name given\n");
995                 return -1;
996         }
997
998         samaccount = samu_new(NULL);
999         if (!samaccount) {
1000                 fprintf(stderr, "Out of memory!\n");
1001                 return -1;
1002         }
1003
1004         if (machinename[strlen(machinename)-1] != '$') {
1005                 name = talloc_asprintf(samaccount, "%s$", machinename);
1006         } else {
1007                 name = machinename;
1008         }
1009
1010         if (!pdb_getsampwnam(samaccount, name)) {
1011                 fprintf (stderr,
1012                          "machine %s does not exist in the passdb\n", name);
1013                 TALLOC_FREE(samaccount);
1014                 return -1;
1015         }
1016
1017         if (!NT_STATUS_IS_OK(pdb_delete_sam_account(samaccount))) {
1018                 fprintf (stderr, "Unable to delete machine %s\n", name);
1019                 TALLOC_FREE(samaccount);
1020                 return -1;
1021         }
1022
1023         TALLOC_FREE(samaccount);
1024         return 0;
1025 }
1026
1027 /*********************************************************
1028  Start here.
1029 **********************************************************/
1030
1031 int main(int argc, const char **argv)
1032 {
1033         static int list_users = False;
1034         static int verbose = False;
1035         static int spstyle = False;
1036         static int machine = False;
1037         static int add_user = False;
1038         static int delete_user = False;
1039         static int modify_user = False;
1040         uint32_t   setparms, checkparms;
1041         int opt;
1042         static char *full_name = NULL;
1043         static char *acct_desc = NULL;
1044         static const char *user_name = NULL;
1045         static char *home_dir = NULL;
1046         static char *home_drive = NULL;
1047         static const char *backend = NULL;
1048         static char *backend_in = NULL;
1049         static char *backend_out = NULL;
1050         static int transfer_groups = False;
1051         static int transfer_account_policies = False;
1052         static int reset_account_policies = False;
1053         static int  force_initialised_password = False;
1054         static char *logon_script = NULL;
1055         static char *profile_path = NULL;
1056         static char *user_domain = NULL;
1057         static char *account_control = NULL;
1058         static char *account_policy = NULL;
1059         static char *user_sid = NULL;
1060         static char *machine_sid = NULL;
1061         static long int account_policy_value = 0;
1062         bool account_policy_value_set = False;
1063         static int badpw_reset = False;
1064         static int hours_reset = False;
1065         static char *pwd_time_format = NULL;
1066         static int pw_from_stdin = False;
1067         struct pdb_methods *bin, *bout;
1068         static char *kickoff_time = NULL;
1069         static char *str_hex_pwd = NULL;
1070         TALLOC_CTX *frame = talloc_stackframe();
1071         struct loadparm_context *lp_ctx = NULL;
1072         NTSTATUS status;
1073         poptContext pc;
1074         bool ok;
1075         struct poptOption long_options[] = {
1076                 POPT_AUTOHELP
1077                 {"list",        'L', POPT_ARG_NONE, &list_users, 0, "list all users", NULL},
1078                 {"verbose",     'v', POPT_ARG_NONE, &verbose, 0, "be verbose", NULL },
1079                 {"smbpasswd-style",     'w',POPT_ARG_NONE, &spstyle, 0, "give output in smbpasswd style", NULL},
1080                 {"user",        'u', POPT_ARG_STRING, &user_name, 0, "use username", "USER" },
1081                 {"account-desc",        'N', POPT_ARG_STRING, &acct_desc, 0, "set account description", NULL},
1082                 {"fullname",    'f', POPT_ARG_STRING, &full_name, 0, "set full name", NULL},
1083                 {"homedir",     'h', POPT_ARG_STRING, &home_dir, 0, "set home directory", NULL},
1084                 {"drive",       'D', POPT_ARG_STRING, &home_drive, 0, "set home drive", NULL},
1085                 {"script",      'S', POPT_ARG_STRING, &logon_script, 0, "set logon script", NULL},
1086                 {"profile",     'p', POPT_ARG_STRING, &profile_path, 0, "set profile path", NULL},
1087                 {"domain",      'I', POPT_ARG_STRING, &user_domain, 0, "set a users' domain", NULL},
1088                 {"user SID",    'U', POPT_ARG_STRING, &user_sid, 0, "set user SID or RID", NULL},
1089                 {"machine SID", 'M', POPT_ARG_STRING, &machine_sid, 0, "set machine SID or RID", NULL},
1090                 {"create",      'a', POPT_ARG_NONE, &add_user, 0, "create user", NULL},
1091                 {"modify",      'r', POPT_ARG_NONE, &modify_user, 0, "modify user", NULL},
1092                 {"machine",     'm', POPT_ARG_NONE, &machine, 0, "account is a machine account", NULL},
1093                 {"delete",      'x', POPT_ARG_NONE, &delete_user, 0, "delete user", NULL},
1094                 {"backend",     'b', POPT_ARG_STRING, &backend, 0, "use different passdb backend as default backend", NULL},
1095                 {"import",      'i', POPT_ARG_STRING, &backend_in, 0, "import user accounts from this backend", NULL},
1096                 {"export",      'e', POPT_ARG_STRING, &backend_out, 0, "export user accounts to this backend", NULL},
1097                 {"group",       'g', POPT_ARG_NONE, &transfer_groups, 0, "use -i and -e for groups", NULL},
1098                 {"policies",    'y', POPT_ARG_NONE, &transfer_account_policies, 0, "use -i and -e to move account policies between backends", NULL},
1099                 {"policies-reset",      0, POPT_ARG_NONE, &reset_account_policies, 0, "restore default policies", NULL},
1100                 {"account-policy",      'P', POPT_ARG_STRING, &account_policy, 0,"value of an account policy (like maximum password age)",NULL},
1101                 {"value",       'C', POPT_ARG_LONG, &account_policy_value, 'C',"set the account policy to this value", NULL},
1102                 {"account-control",     'c', POPT_ARG_STRING, &account_control, 0, "Values of account control", NULL},
1103                 {"force-initialized-passwords", 0, POPT_ARG_NONE, &force_initialised_password, 0, "Force initialization of corrupt password strings in a passdb backend", NULL},
1104                 {"bad-password-count-reset", 'z', POPT_ARG_NONE, &badpw_reset, 0, "reset bad password count", NULL},
1105                 {"logon-hours-reset", 'Z', POPT_ARG_NONE, &hours_reset, 0, "reset logon hours", NULL},
1106                 {"time-format", 0, POPT_ARG_STRING, &pwd_time_format, 0, "The time format for time parameters", NULL },
1107                 {"password-from-stdin", 't', POPT_ARG_NONE, &pw_from_stdin, 0, "get password from standard in", NULL},
1108                 {"kickoff-time", 'K', POPT_ARG_STRING, &kickoff_time, 0, "set the kickoff time", NULL},
1109                 {"set-nt-hash", 0, POPT_ARG_STRING, &str_hex_pwd, 0, "set password from nt-hash", NULL},
1110                 POPT_COMMON_SAMBA
1111                 POPT_COMMON_VERSION
1112                 POPT_TABLEEND
1113         };
1114
1115         bin = bout = NULL;
1116
1117         smb_init_locale();
1118
1119         ok = samba_cmdline_init(frame,
1120                                 SAMBA_CMDLINE_CONFIG_CLIENT,
1121                                 false /* require_smbconf */);
1122         if (!ok) {
1123                 DBG_ERR("Failed to init cmdline parser!\n");
1124                 TALLOC_FREE(frame);
1125                 exit(1);
1126         }
1127         lp_ctx = samba_cmdline_get_lp_ctx();
1128
1129         pc = samba_popt_get_context(getprogname(),
1130                                     argc,
1131                                     argv,
1132                                     long_options,
1133                                     POPT_CONTEXT_KEEP_FIRST);
1134         if (pc == NULL) {
1135                 DBG_ERR("Failed to setup popt context!\n");
1136                 TALLOC_FREE(frame);
1137                 exit(1);
1138         }
1139
1140         while((opt = poptGetNextOpt(pc)) != -1) {
1141                 switch (opt) {
1142                 case 'C':
1143                         account_policy_value_set = True;
1144                         break;
1145                 case POPT_ERROR_BADOPT:
1146                         fprintf(stderr, "\nInvalid option %s: %s\n\n",
1147                                 poptBadOption(pc, 0), poptStrerror(opt));
1148                         poptPrintUsage(pc, stderr, 0);
1149                         exit(1);
1150                 }
1151         }
1152
1153         poptGetArg(pc); /* Drop argv[0], the program name */
1154
1155         if (user_name == NULL) {
1156                 if (poptPeekArg(pc)) {
1157                         user_name = talloc_strdup(frame, poptGetArg(pc));
1158                         if (user_name == NULL) {
1159                                 fprintf(stderr, "out of memory\n");
1160                                 TALLOC_FREE(frame);
1161                                 exit(1);
1162                         }
1163                 }
1164         }
1165
1166         setparms =      (backend ? BIT_BACKEND : 0) +
1167                         (verbose ? BIT_VERBOSE : 0) +
1168                         (spstyle ? BIT_SPSTYLE : 0) +
1169                         (full_name ? BIT_FULLNAME : 0) +
1170                         (home_dir ? BIT_HOMEDIR : 0) +
1171                         (home_drive ? BIT_HDIRDRIVE : 0) +
1172                         (logon_script ? BIT_LOGSCRIPT : 0) +
1173                         (profile_path ? BIT_PROFILE : 0) +
1174                         (user_domain ? BIT_USERDOMAIN : 0) +
1175                         (machine ? BIT_MACHINE : 0) +
1176                         (user_name ? BIT_USER : 0) +
1177                         (list_users ? BIT_LIST : 0) +
1178                         (force_initialised_password ? BIT_FIX_INIT : 0) +
1179                         (user_sid ? BIT_USERSIDS : 0) +
1180                         (machine_sid ? BIT_USERSIDS : 0) +
1181                         (modify_user ? BIT_MODIFY : 0) +
1182                         (add_user ? BIT_CREATE : 0) +
1183                         (delete_user ? BIT_DELETE : 0) +
1184                         (account_control ? BIT_ACCTCTRL : 0) +
1185                         (account_policy ? BIT_ACCPOLICY : 0) +
1186                         (account_policy_value_set ? BIT_ACCPOLVAL : 0) +
1187                         (backend_in ? BIT_IMPORT : 0) +
1188                         (backend_out ? BIT_EXPORT : 0) +
1189                         (badpw_reset ? BIT_BADPWRESET : 0) +
1190                         (hours_reset ? BIT_LOGONHOURS : 0) +
1191                         (kickoff_time ? BIT_KICKOFFTIME : 0) +
1192                         (str_hex_pwd ? BIT_PWSETNTHASH : 0 ) +
1193                         (acct_desc ? BIT_DESCRIPTION : 0);
1194
1195
1196         if (setparms & BIT_BACKEND) {
1197                 /* HACK: set the global passdb backend by overwriting globals.
1198                  * This way we can use regular pdb functions for default
1199                  * operations that do not involve passdb migrations */
1200                 lpcfg_set_cmdline(lp_ctx, "passdb backend", backend);
1201         } else {
1202                 backend = lp_passdb_backend();
1203         }
1204
1205         if (!initialize_password_db(False, NULL)) {
1206                 fprintf(stderr, "Can't initialize passdb backend.\n");
1207                 exit(1);
1208         }
1209
1210         /* the lowest bit options are always accepted */
1211         checkparms = setparms & ~MASK_ALWAYS_GOOD;
1212
1213         if (checkparms & BIT_FIX_INIT) {
1214                 poptFreeContext(pc);
1215                 return fix_users_list();
1216         }
1217
1218         /* account policy operations */
1219         if ((checkparms & BIT_ACCPOLICY) && !(checkparms & ~(BIT_ACCPOLICY + BIT_ACCPOLVAL))) {
1220                 uint32_t value;
1221                 enum pdb_policy_type field = account_policy_name_to_typenum(account_policy);
1222                 if (field == 0) {
1223                         const char **names;
1224                         int count;
1225                         int i;
1226                         account_policy_names_list(talloc_tos(), &names, &count);
1227                         fprintf(stderr, "No account policy by that name!\n");
1228                         if (count !=0) {
1229                                 fprintf(stderr, "Account policy names are:\n");
1230                                 for (i = 0; i < count ; i++) {
1231                                         d_fprintf(stderr, "%s\n", names[i]);
1232                                 }
1233                         }
1234                         TALLOC_FREE(names);
1235                         exit(1);
1236                 }
1237                 if (!pdb_get_account_policy(field, &value)) {
1238                         fprintf(stderr, "valid account policy, but unable to fetch value!\n");
1239                         if (!account_policy_value_set)
1240                                 exit(1);
1241                 }
1242                 printf("account policy \"%s\" description: %s\n", account_policy, account_policy_get_desc(field));
1243                 if (account_policy_value_set) {
1244                         printf("account policy \"%s\" value was: %u\n", account_policy, value);
1245                         if (!pdb_set_account_policy(field, account_policy_value)) {
1246                                 fprintf(stderr, "valid account policy, but unable to set value!\n");
1247                                 exit(1);
1248                         }
1249                         printf("account policy \"%s\" value is now: %lu\n", account_policy, account_policy_value);
1250                         exit(0);
1251                 } else {
1252                         printf("account policy \"%s\" value is: %u\n", account_policy, value);
1253                         exit(0);
1254                 }
1255         }
1256
1257         if (reset_account_policies) {
1258                 if (reinit_account_policies()) {
1259                         exit(1);
1260                 }
1261
1262                 exit(0);
1263         }
1264
1265         /* import and export operations */
1266
1267         if (((checkparms & BIT_IMPORT) ||
1268              (checkparms & BIT_EXPORT)) &&
1269             !(checkparms & ~(BIT_IMPORT +BIT_EXPORT +BIT_USER))) {
1270
1271                 poptFreeContext(pc);
1272
1273                 if (backend_in) {
1274                         status = make_pdb_method_name(&bin, backend_in);
1275                 } else {
1276                         status = make_pdb_method_name(&bin, backend);
1277                 }
1278
1279                 if (!NT_STATUS_IS_OK(status)) {
1280                         fprintf(stderr, "Unable to initialize %s.\n",
1281                                 backend_in ? backend_in : backend);
1282                         return 1;
1283                 }
1284
1285                 if (backend_out) {
1286                         status = make_pdb_method_name(&bout, backend_out);
1287                 } else {
1288                         status = make_pdb_method_name(&bout, backend);
1289                 }
1290
1291                 if (!NT_STATUS_IS_OK(status)) {
1292                         fprintf(stderr, "Unable to initialize %s.\n",
1293                                 backend_out ? backend_out : backend);
1294                         return 1;
1295                 }
1296
1297                 if (transfer_account_policies) {
1298
1299                         if (!(checkparms & BIT_USER)) {
1300                                 return export_account_policies(bin, bout);
1301                         }
1302
1303                 } else  if (transfer_groups) {
1304
1305                         if (!(checkparms & BIT_USER)) {
1306                                 return export_groups(bin, bout);
1307                         }
1308
1309                 } else {
1310                         return export_database(bin, bout,
1311                                 (checkparms & BIT_USER) ? user_name : NULL);
1312                 }
1313         }
1314
1315         /* if BIT_USER is defined but nothing else then threat it as -l -u for compatibility */
1316         /* fake up BIT_LIST if only BIT_USER is defined */
1317         if ((checkparms & BIT_USER) && !(checkparms & ~BIT_USER)) {
1318                 checkparms += BIT_LIST;
1319         }
1320
1321         /* modify flag is optional to maintain backwards compatibility */
1322         /* fake up BIT_MODIFY if BIT_USER  and at least one of MASK_USER_GOOD is defined */
1323         if (!((checkparms & ~MASK_USER_GOOD) & ~BIT_USER) && (checkparms & MASK_USER_GOOD)) {
1324                 checkparms += BIT_MODIFY;
1325         }
1326
1327         /* list users operations */
1328         if (checkparms & BIT_LIST) {
1329                 if (!(checkparms & ~BIT_LIST)) {
1330                         poptFreeContext(pc);
1331                         return print_users_list(verbose, spstyle);
1332                 }
1333                 if (!(checkparms & ~(BIT_USER + BIT_LIST))) {
1334                         poptFreeContext(pc);
1335                         return print_user_info(user_name, verbose, spstyle);
1336                 }
1337         }
1338
1339         /* mask out users options */
1340         checkparms &= ~MASK_USER_GOOD;
1341
1342         /* if bad password count is reset, we must be modifying */
1343         if (checkparms & BIT_BADPWRESET) {
1344                 checkparms |= BIT_MODIFY;
1345                 checkparms &= ~BIT_BADPWRESET;
1346         }
1347
1348         /* if logon hours is reset, must modify */
1349         if (checkparms & BIT_LOGONHOURS) {
1350                 checkparms |= BIT_MODIFY;
1351                 checkparms &= ~BIT_LOGONHOURS;
1352         }
1353
1354         /* account operation */
1355         if ((checkparms & BIT_CREATE) || (checkparms & BIT_MODIFY) || (checkparms & BIT_DELETE)) {
1356                 /* check use of -u option */
1357                 if (!(checkparms & BIT_USER)) {
1358                         fprintf (stderr, "Username not specified! (use -u option)\n");
1359                         poptFreeContext(pc);
1360                         return -1;
1361                 }
1362
1363                 /* account creation operations */
1364                 if (!(checkparms & ~(BIT_CREATE + BIT_USER + BIT_MACHINE))) {
1365                         poptFreeContext(pc);
1366                         if (checkparms & BIT_MACHINE) {
1367                                 return new_machine(user_name, machine_sid);
1368                         } else {
1369                                 return new_user(user_name, full_name,
1370                                                 home_dir, home_drive,
1371                                                 logon_script, profile_path,
1372                                                 user_sid, pw_from_stdin);
1373                         }
1374                 }
1375
1376                 /* account deletion operations */
1377                 if (!(checkparms & ~(BIT_DELETE + BIT_USER + BIT_MACHINE))) {
1378                         poptFreeContext(pc);
1379                         if (checkparms & BIT_MACHINE) {
1380                                 return delete_machine_entry(user_name);
1381                         } else {
1382                                 return delete_user_entry(user_name);
1383                         }
1384                 }
1385
1386                 /* account modification operations */
1387                 if (!(checkparms & ~(BIT_MODIFY + BIT_USER + BIT_MACHINE))) {
1388                         poptFreeContext(pc);
1389                         if (checkparms & BIT_MACHINE) {
1390                                 return set_machine_info(user_name,
1391                                                         account_control,
1392                                                         machine_sid);
1393                         } else {
1394                                 return set_user_info(user_name, full_name,
1395                                                      home_dir, acct_desc,
1396                                                      home_drive, logon_script,
1397                                                      profile_path, account_control,
1398                                                      user_sid, user_domain,
1399                                                      badpw_reset, hours_reset,
1400                                                      kickoff_time, str_hex_pwd);
1401                         }
1402                 }
1403         }
1404
1405         if (setparms >= 0x20) {
1406                 fprintf (stderr, "Incompatible or insufficient options on command line!\n");
1407         }
1408         poptPrintHelp(pc, stderr, 0);
1409
1410         poptFreeContext(pc);
1411         TALLOC_FREE(frame);
1412         return 1;
1413 }