utils/smbpasswd.c

説明を見る。
00001 /*
00002  * Unix SMB/CIFS implementation. 
00003  * Copyright (C) Jeremy Allison 1995-1998
00004  * Copyright (C) Tim Potter     2001
00005  * 
00006  * This program is free software; you can redistribute it and/or modify it
00007  * under the terms of the GNU General Public License as published by the
00008  * Free Software Foundation; either version 2 of the License, or (at your
00009  * option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00014  * more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License along with
00017  * this program; if not, write to the Free Software Foundation, Inc., 675
00018  * Mass Ave, Cambridge, MA 02139, USA.  */
00019 
00020 #include "includes.h"
00021 
00022 extern BOOL AllowDebugChange;
00023 
00024 /*
00025  * Next two lines needed for SunOS and don't
00026  * hurt anything else...
00027  */
00028 extern char *optarg;
00029 extern int optind;
00030 
00031 /* forced running in root-mode */
00032 static BOOL got_username = False;
00033 static BOOL stdin_passwd_get = False;
00034 static fstring user_name;
00035 static char *new_passwd = NULL;
00036 static const char *remote_machine = NULL;
00037 
00038 static fstring ldap_secret;
00039 
00040 
00041 /*********************************************************
00042  Print command usage on stderr and die.
00043 **********************************************************/
00044 static void usage(void)
00045 {
00046         printf("When run by root:\n");
00047         printf("    smbpasswd [options] [username]\n");
00048         printf("otherwise:\n");
00049         printf("    smbpasswd [options]\n\n");
00050 
00051         printf("options:\n");
00052         printf("  -L                   local mode (must be first option)\n");
00053         printf("  -h                   print this usage message\n");
00054         printf("  -s                   use stdin for password prompt\n");
00055         printf("  -c smb.conf file     Use the given path to the smb.conf file\n");
00056         printf("  -D LEVEL             debug level\n");
00057         printf("  -r MACHINE           remote machine\n");
00058         printf("  -U USER              remote username\n");
00059 
00060         printf("extra options when run by root or in local mode:\n");
00061         printf("  -a                   add user\n");
00062         printf("  -d                   disable user\n");
00063         printf("  -e                   enable user\n");
00064         printf("  -i                   interdomain trust account\n");
00065         printf("  -m                   machine trust account\n");
00066         printf("  -n                   set no password\n");
00067         printf("  -W                   use stdin ldap admin password\n");
00068         printf("  -w PASSWORD          ldap admin password\n");
00069         printf("  -x                   delete user\n");
00070         printf("  -R ORDER             name resolve order\n");
00071 
00072         exit(1);
00073 }
00074 
00075 static void set_line_buffering(FILE *f)
00076 {
00077         setvbuf(f, NULL, _IOLBF, 0);
00078 }
00079 
00080 /*******************************************************************
00081  Process command line options
00082  ******************************************************************/
00083 
00084 static int process_options(int argc, char **argv, int local_flags)
00085 {
00086         int ch;
00087         pstring configfile;
00088         pstrcpy(configfile, dyn_CONFIGFILE);
00089 
00090         local_flags |= LOCAL_SET_PASSWORD;
00091 
00092         ZERO_STRUCT(user_name);
00093 
00094         user_name[0] = '\0';
00095 
00096         while ((ch = getopt(argc, argv, "c:axdehminjr:sw:R:D:U:LW")) != EOF) {
00097                 switch(ch) {
00098                 case 'L':
00099 #if !defined(DEVELOPER)
00100                         if (getuid() != 0) {
00101                                 fprintf(stderr, "smbpasswd -L can only be used by root.\n");
00102                                 exit(1);
00103                         }
00104 #endif
00105                         local_flags |= LOCAL_AM_ROOT;
00106                         break;
00107                 case 'c':
00108                         pstrcpy(configfile,optarg);
00109                         break;
00110                 case 'a':
00111                         local_flags |= LOCAL_ADD_USER;
00112                         break;
00113                 case 'x':
00114                         local_flags |= LOCAL_DELETE_USER;
00115                         local_flags &= ~LOCAL_SET_PASSWORD;
00116                         break;
00117                 case 'd':
00118                         local_flags |= LOCAL_DISABLE_USER;
00119                         local_flags &= ~LOCAL_SET_PASSWORD;
00120                         break;
00121                 case 'e':
00122                         local_flags |= LOCAL_ENABLE_USER;
00123                         local_flags &= ~LOCAL_SET_PASSWORD;
00124                         break;
00125                 case 'm':
00126                         local_flags |= LOCAL_TRUST_ACCOUNT;
00127                         break;
00128                 case 'i':
00129                         local_flags |= LOCAL_INTERDOM_ACCOUNT;
00130                         break;
00131                 case 'j':
00132                         d_printf("See 'net join' for this functionality\n");
00133                         exit(1);
00134                         break;
00135                 case 'n':
00136                         local_flags |= LOCAL_SET_NO_PASSWORD;
00137                         local_flags &= ~LOCAL_SET_PASSWORD;
00138                         new_passwd = smb_xstrdup("NO PASSWORD");
00139                         break;
00140                 case 'r':
00141                         remote_machine = optarg;
00142                         break;
00143                 case 's':
00144                         set_line_buffering(stdin);
00145                         set_line_buffering(stdout);
00146                         set_line_buffering(stderr);
00147                         stdin_passwd_get = True;
00148                         break;
00149                 case 'w':
00150                         local_flags |= LOCAL_SET_LDAP_ADMIN_PW;
00151                         fstrcpy(ldap_secret, optarg);
00152                         break;
00153                 case 'R':
00154                         lp_set_name_resolve_order(optarg);
00155                         break;
00156                 case 'D':
00157                         DEBUGLEVEL = atoi(optarg);
00158                         break;
00159                 case 'U': {
00160                         got_username = True;
00161                         fstrcpy(user_name, optarg);
00162                         break;
00163                 case 'W':
00164                         local_flags |= LOCAL_SET_LDAP_ADMIN_PW;
00165                         *ldap_secret = '\0';
00166                         break;
00167                 }
00168                 case 'h':
00169                 default:
00170                         usage();
00171                 }
00172         }
00173         
00174         argc -= optind;
00175         argv += optind;
00176 
00177         switch(argc) {
00178         case 0:
00179                 if (!got_username)
00180                         fstrcpy(user_name, "");
00181                 break;
00182         case 1:
00183                 if (!(local_flags & LOCAL_AM_ROOT)) {
00184                         usage();
00185                 } else {
00186                         if (got_username) {
00187                                 usage();
00188                         } else {
00189                                 fstrcpy(user_name, argv[0]);
00190                         }
00191                 }
00192                 break;
00193         default:
00194                 usage();
00195         }
00196 
00197         if (!lp_load(configfile,True,False,False,True)) {
00198                 fprintf(stderr, "Can't load %s - run testparm to debug it\n", 
00199                         configfile);
00200                 exit(1);
00201         }
00202 
00203         return local_flags;
00204 }
00205 
00206 /*************************************************************
00207  Utility function to prompt for new password.
00208 *************************************************************/
00209 static char *prompt_for_new_password(BOOL stdin_get)
00210 {
00211         char *p;
00212         fstring new_pw;
00213 
00214         ZERO_ARRAY(new_pw);
00215  
00216         p = get_pass("New SMB password:", stdin_get);
00217 
00218         fstrcpy(new_pw, p);
00219         SAFE_FREE(p);
00220 
00221         p = get_pass("Retype new SMB password:", stdin_get);
00222 
00223         if (strcmp(p, new_pw)) {
00224                 fprintf(stderr, "Mismatch - password unchanged.\n");
00225                 ZERO_ARRAY(new_pw);
00226                 SAFE_FREE(p);
00227                 return NULL;
00228         }
00229 
00230         return p;
00231 }
00232 
00233 
00234 /*************************************************************
00235  Change a password either locally or remotely.
00236 *************************************************************/
00237 
00238 static NTSTATUS password_change(const char *remote_mach, char *username, 
00239                                 char *old_passwd, char *new_pw,
00240                                 int local_flags)
00241 {
00242         NTSTATUS ret;
00243         pstring err_str;
00244         pstring msg_str;
00245 
00246         if (remote_mach != NULL) {
00247                 if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|
00248                                                         LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) {
00249                         /* these things can't be done remotely yet */
00250                         return NT_STATUS_UNSUCCESSFUL;
00251                 }
00252                 ret = remote_password_change(remote_mach, username, 
00253                                              old_passwd, new_pw, err_str, sizeof(err_str));
00254                 if(*err_str)
00255                         fprintf(stderr, "%s", err_str);
00256                 return ret;
00257         }
00258         
00259         ret = local_password_change(username, local_flags, new_pw, 
00260                                      err_str, sizeof(err_str), msg_str, sizeof(msg_str));
00261 
00262         if(*msg_str)
00263                 printf("%s", msg_str);
00264         if(*err_str)
00265                 fprintf(stderr, "%s", err_str);
00266 
00267         return ret;
00268 }
00269 
00270 /*******************************************************************
00271  Store the LDAP admin password in secrets.tdb
00272  ******************************************************************/
00273 static BOOL store_ldap_admin_pw (char* pw)
00274 {       
00275         if (!pw) 
00276                 return False;
00277 
00278         if (!secrets_init())
00279                 return False;
00280         
00281         return secrets_store_ldap_pw(lp_ldap_admin_dn(), pw);
00282 }
00283 
00284 
00285 /*************************************************************
00286  Handle password changing for root.
00287 *************************************************************/
00288 
00289 static int process_root(int local_flags)
00290 {
00291         struct passwd  *pwd;
00292         int result = 0;
00293         char *old_passwd = NULL;
00294 
00295         if (local_flags & LOCAL_SET_LDAP_ADMIN_PW) {
00296                 char *ldap_admin_dn = lp_ldap_admin_dn();
00297                 if ( ! *ldap_admin_dn ) {
00298                         DEBUG(0,("ERROR: 'ldap admin dn' not defined! Please check your smb.conf\n"));
00299                         goto done;
00300                 }
00301 
00302                 printf("Setting stored password for \"%s\" in secrets.tdb\n", ldap_admin_dn);
00303                 if ( ! *ldap_secret ) {
00304                         new_passwd = prompt_for_new_password(stdin_passwd_get);
00305                         fstrcpy(ldap_secret, new_passwd);
00306                 }
00307                 if (!store_ldap_admin_pw(ldap_secret)) {
00308                         DEBUG(0,("ERROR: Failed to store the ldap admin password!\n"));
00309                 }
00310                 goto done;
00311         }
00312 
00313         /* Ensure passdb startup(). */
00314         if(!initialize_password_db(False)) {
00315                 DEBUG(0, ("Failed to open passdb!\n"));
00316                 exit(1);
00317         }
00318                 
00319         /* Ensure we have a SAM sid. */
00320         get_global_sam_sid();
00321 
00322         /*
00323          * Ensure both add/delete user are not set
00324          * Ensure add/delete user and either remote machine or join domain are
00325          * not both set.
00326          */     
00327         if(((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) == (LOCAL_ADD_USER|LOCAL_DELETE_USER)) || 
00328            ((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) && 
00329                 (remote_machine != NULL))) {
00330                 usage();
00331         }
00332         
00333         /* Only load interfaces if we are doing network operations. */
00334 
00335         if (remote_machine) {
00336                 load_interfaces();
00337         }
00338 
00339         if (!user_name[0] && (pwd = getpwuid_alloc(NULL, geteuid()))) {
00340                 fstrcpy(user_name, pwd->pw_name);
00341                 TALLOC_FREE(pwd);
00342         } 
00343 
00344         if (!user_name[0]) {
00345                 fprintf(stderr,"You must specify a username\n");
00346                 exit(1);
00347         }
00348 
00349         if (local_flags & LOCAL_TRUST_ACCOUNT) {
00350                 /* add the $ automatically */
00351                 static fstring buf;
00352 
00353                 /*
00354                  * Remove any trailing '$' before we
00355                  * generate the initial machine password.
00356                  */
00357 
00358                 if (user_name[strlen(user_name)-1] == '$') {
00359                         user_name[strlen(user_name)-1] = 0;
00360                 }
00361 
00362                 if (local_flags & LOCAL_ADD_USER) {
00363                         SAFE_FREE(new_passwd);
00364                         new_passwd = smb_xstrdup(user_name);
00365                         strlower_m(new_passwd);
00366                 }
00367 
00368                 /*
00369                  * Now ensure the username ends in '$' for
00370                  * the machine add.
00371                  */
00372 
00373                 slprintf(buf, sizeof(buf)-1, "%s$", user_name);
00374                 fstrcpy(user_name, buf);
00375         } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
00376                 static fstring buf;
00377 
00378                 if ((local_flags & LOCAL_ADD_USER) && (new_passwd == NULL)) {
00379                         /*
00380                          * Prompt for trusting domain's account password
00381                          */
00382                         new_passwd = prompt_for_new_password(stdin_passwd_get);
00383                         if(!new_passwd) {
00384                                 fprintf(stderr, "Unable to get newpassword.\n");
00385                                 exit(1);
00386                         }
00387                 }
00388                 
00389                 /* prepare uppercased and '$' terminated username */
00390                 slprintf(buf, sizeof(buf) - 1, "%s$", user_name);
00391                 fstrcpy(user_name, buf);
00392                 
00393         } else {
00394                 
00395                 if (remote_machine != NULL) {
00396                         old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
00397                 }
00398                 
00399                 if (!(local_flags & LOCAL_SET_PASSWORD)) {
00400                         
00401                         /*
00402                          * If we are trying to enable a user, first we need to find out
00403                          * if they are using a modern version of the smbpasswd file that
00404                          * disables a user by just writing a flag into the file. If so
00405                          * then we can re-enable a user without prompting for a new
00406                          * password. If not (ie. they have a no stored password in the
00407                          * smbpasswd file) then we need to prompt for a new password.
00408                          */
00409                         
00410                         if(local_flags & LOCAL_ENABLE_USER) {
00411                                 struct samu *sampass = NULL;
00412                                 
00413                                 sampass = samu_new( NULL );
00414                                 if (!sampass) {
00415                                         fprintf(stderr, "talloc fail for struct samu.\n");
00416                                         exit(1);
00417                                 }
00418                                 if (!pdb_getsampwnam(sampass, user_name)) {
00419                                         fprintf(stderr, "Failed to find user %s in passdb backend.\n",
00420                                                 user_name );
00421                                         exit(1);
00422                                 }
00423 
00424                                 if(pdb_get_nt_passwd(sampass) == NULL) {
00425                                         local_flags |= LOCAL_SET_PASSWORD;
00426                                 }
00427                                 TALLOC_FREE(sampass);
00428                         }
00429                 }
00430                 
00431                 if((local_flags & LOCAL_SET_PASSWORD) && (new_passwd == NULL)) {
00432                         new_passwd = prompt_for_new_password(stdin_passwd_get);
00433                         
00434                         if(!new_passwd) {
00435                                 fprintf(stderr, "Unable to get new password.\n");
00436                                 exit(1);
00437                         }
00438                 }
00439         }
00440 
00441         if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name,
00442                                              old_passwd, new_passwd,
00443                                              local_flags))) {
00444                 fprintf(stderr,"Failed to modify password entry for user %s\n", user_name);
00445                 result = 1;
00446                 goto done;
00447         } 
00448 
00449         if(remote_machine) {
00450                 printf("Password changed for user %s on %s.\n", user_name, remote_machine );
00451         } else if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD|LOCAL_SET_PASSWORD))) {
00452                 struct samu *sampass = NULL;
00453                 
00454                 sampass = samu_new( NULL );
00455                 if (!sampass) {
00456                         fprintf(stderr, "talloc fail for struct samu.\n");
00457                         exit(1);
00458                 }
00459 
00460                 if (!pdb_getsampwnam(sampass, user_name)) {
00461                         fprintf(stderr, "Failed to find user %s in passdb backend.\n",
00462                                 user_name );
00463                         exit(1);
00464                 }
00465 
00466                 printf("Password changed for user %s.", user_name );
00467                 if(pdb_get_acct_ctrl(sampass)&ACB_DISABLED) {
00468                         printf(" User has disabled flag set.");
00469                 }
00470                 if(pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ) {
00471                         printf(" User has no password flag set.");
00472                 }
00473                 printf("\n");
00474                 TALLOC_FREE(sampass);
00475         }
00476 
00477  done:
00478         SAFE_FREE(new_passwd);
00479         return result;
00480 }
00481 
00482 
00483 /*************************************************************
00484  Handle password changing for non-root.
00485 *************************************************************/
00486 
00487 static int process_nonroot(int local_flags)
00488 {
00489         struct passwd  *pwd = NULL;
00490         int result = 0;
00491         char *old_pw = NULL;
00492         char *new_pw = NULL;
00493 
00494         if (local_flags & ~(LOCAL_AM_ROOT | LOCAL_SET_PASSWORD)) {
00495                 /* Extra flags that we can't honor non-root */
00496                 usage();
00497         }
00498 
00499         if (!user_name[0]) {
00500                 pwd = getpwuid_alloc(NULL, getuid());
00501                 if (pwd) {
00502                         fstrcpy(user_name,pwd->pw_name);
00503                         TALLOC_FREE(pwd);
00504                 } else {
00505                         fprintf(stderr, "smbpasswd: cannot lookup user name for uid %u\n", (unsigned int)getuid());
00506                         exit(1);
00507                 }
00508         }
00509         
00510         /*
00511          * A non-root user is always setting a password
00512          * via a remote machine (even if that machine is
00513          * localhost).
00514          */     
00515 
00516         load_interfaces(); /* Delayed from main() */
00517 
00518         if (remote_machine == NULL) {
00519                 remote_machine = "127.0.0.1";
00520         }
00521 
00522         if (remote_machine != NULL) {
00523                 old_pw = get_pass("Old SMB password:",stdin_passwd_get);
00524         }
00525         
00526         if (!new_passwd) {
00527                 new_pw = prompt_for_new_password(stdin_passwd_get);
00528         }
00529         else
00530                 new_pw = smb_xstrdup(new_passwd);
00531         
00532         if (!new_pw) {
00533                 fprintf(stderr, "Unable to get new password.\n");
00534                 exit(1);
00535         }
00536 
00537         if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name, old_pw,
00538                                              new_pw, 0))) {
00539                 fprintf(stderr,"Failed to change password for %s\n", user_name);
00540                 result = 1;
00541                 goto done;
00542         }
00543 
00544         printf("Password changed for user %s\n", user_name);
00545 
00546  done:
00547         SAFE_FREE(old_pw);
00548         SAFE_FREE(new_pw);
00549 
00550         return result;
00551 }
00552 
00553 
00554 
00555 /*********************************************************
00556  Start here.
00557 **********************************************************/
00558 int main(int argc, char **argv)
00559 {       
00560         int local_flags = 0;
00561         
00562         AllowDebugChange = False;
00563 
00564 #if defined(HAVE_SET_AUTH_PARAMETERS)
00565         set_auth_parameters(argc, argv);
00566 #endif /* HAVE_SET_AUTH_PARAMETERS */
00567 
00568         if (getuid() == 0) {
00569                 local_flags = LOCAL_AM_ROOT;
00570         }
00571 
00572         load_case_tables();
00573 
00574         local_flags = process_options(argc, argv, local_flags);
00575 
00576         setup_logging("smbpasswd", True);
00577         
00578         /*
00579          * Set the machine NETBIOS name if not already
00580          * set from the config file. 
00581          */ 
00582     
00583         if (!init_names())
00584                 return 1;
00585 
00586         /* Check the effective uid - make sure we are not setuid */
00587         if (is_setuid_root()) {
00588                 fprintf(stderr, "smbpasswd must *NOT* be setuid root.\n");
00589                 exit(1);
00590         }
00591 
00592         if (local_flags & LOCAL_AM_ROOT) {
00593                 secrets_init();
00594                 return process_root(local_flags);
00595         } 
00596 
00597         return process_nonroot(local_flags);
00598 }

Sambaに対してSat Aug 29 21:23:30 2009に生成されました。  doxygen 1.4.7