lib/popt_common.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Common popt routines
00004 
00005    Copyright (C) Tim Potter 2001,2002
00006    Copyright (C) Jelmer Vernooij 2002,2003
00007    Copyright (C) James Peach 2006
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013    
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018    
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 */
00023 
00024 #include "includes.h"
00025 
00026 /* Handle command line options:
00027  *              -d,--debuglevel 
00028  *              -s,--configfile 
00029  *              -O,--socket-options 
00030  *              -V,--version
00031  *              -l,--log-base
00032  *              -n,--netbios-name
00033  *              -W,--workgroup
00034  *              -i,--scope
00035  */
00036 
00037 extern pstring user_socket_options;
00038 extern BOOL AllowDebugChange;
00039 extern BOOL override_logfile;
00040 
00041 struct user_auth_info cmdline_auth_info;
00042 
00043 static void set_logfile(poptContext con, const char * arg)
00044 {
00045 
00046         pstring logfile;
00047         const char *pname;
00048         
00049         /* Find out basename of current program */
00050         pname = strrchr_m(poptGetInvocationName(con),'/');
00051 
00052         if (!pname)
00053                 pname = poptGetInvocationName(con);
00054         else 
00055                 pname++;
00056 
00057         pstr_sprintf(logfile, "%s/%s.log", arg, pname);
00058         lp_set_logfile(logfile);
00059 }
00060 
00061 static void popt_common_callback(poptContext con,
00062                            enum poptCallbackReason reason,
00063                            const struct poptOption *opt,
00064                            const char *arg, const void *data)
00065 {
00066 
00067         if (reason == POPT_CALLBACK_REASON_PRE) {
00068                 set_logfile(con, dyn_LOGFILEBASE);
00069                 return;
00070         }
00071 
00072         switch(opt->val) {
00073         case 'd':
00074                 if (arg) {
00075                         debug_parse_levels(arg);
00076                         AllowDebugChange = False;
00077                 }
00078                 break;
00079 
00080         case 'V':
00081                 printf( "Version %s\n", SAMBA_VERSION_STRING);
00082                 exit(0);
00083                 break;
00084 
00085         case 'O':
00086                 if (arg) {
00087                         pstrcpy(user_socket_options,arg);
00088                 }
00089                 break;
00090 
00091         case 's':
00092                 if (arg) {
00093                         pstrcpy(dyn_CONFIGFILE, arg);
00094                 }
00095                 break;
00096 
00097         case 'n':
00098                 if (arg) {
00099                         set_global_myname_override(arg);
00100                 }
00101                 break;
00102 
00103         case 'l':
00104                 if (arg) {
00105                         set_logfile(con, arg);
00106                         override_logfile = True;
00107                         pstr_sprintf(dyn_LOGFILEBASE, "%s", arg);
00108                 }
00109                 break;
00110 
00111         case 'i':
00112                 if (arg) {
00113                           set_global_scope(arg);
00114                 }
00115                 break;
00116 
00117         case 'W':
00118                 if (arg) {
00119                         set_global_myworkgroup(arg);
00120                 }
00121                 break;
00122         }
00123 }
00124 
00125 struct poptOption popt_common_connection[] = {
00126         { NULL, 0, POPT_ARG_CALLBACK, (void *)popt_common_callback },
00127         { "socket-options", 'O', POPT_ARG_STRING, NULL, 'O', "socket options to use",
00128           "SOCKETOPTIONS" },
00129         { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" },
00130         { "workgroup", 'W', POPT_ARG_STRING, NULL, 'W', "Set the workgroup name", "WORKGROUP" },
00131         { "scope", 'i', POPT_ARG_STRING, NULL, 'i', "Use this Netbios scope", "SCOPE" },
00132 
00133         POPT_TABLEEND
00134 };
00135 
00136 struct poptOption popt_common_samba[] = {
00137         { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, (void *)popt_common_callback },
00138         { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" },
00139         { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternate configuration file", "CONFIGFILE" },
00140         { "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Base name for log files", "LOGFILEBASE" },
00141         { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" },
00142         POPT_TABLEEND
00143 };
00144 
00145 struct poptOption popt_common_version[] = {
00146         { NULL, 0, POPT_ARG_CALLBACK, (void *)popt_common_callback },
00147         { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version" },
00148         POPT_TABLEEND
00149 };
00150 
00151 
00152 /* Handle command line options:
00153  *              --sbindir
00154  *              --bindir
00155  *              --swatdir
00156  *              --lmhostsfile
00157  *              --libdir
00158  *              --shlibext
00159  *              --lockdir
00160  *              --piddir
00161  *              --smb-passwd-file
00162  *              --private-dir
00163  */
00164 
00165 enum dyn_item{
00166         DYN_SBINDIR = 1,
00167         DYN_BINDIR,
00168         DYN_SWATDIR,
00169         DYN_LMHOSTSFILE,
00170         DYN_LIBDIR,
00171         DYN_SHLIBEXT,
00172         DYN_LOCKDIR,
00173         DYN_PIDDIR,
00174         DYN_SMB_PASSWD_FILE,
00175         DYN_PRIVATE_DIR,
00176 };
00177 
00178 
00179 static void popt_dynconfig_callback(poptContext con,
00180                            enum poptCallbackReason reason,
00181                            const struct poptOption *opt,
00182                            const char *arg, const void *data)
00183 {
00184 
00185         switch (opt->val) {
00186         case DYN_SBINDIR:
00187                 if (arg) {
00188                         dyn_SBINDIR = SMB_STRDUP(arg);
00189                 }
00190                 break;
00191 
00192         case DYN_BINDIR:
00193                 if (arg) {
00194                         dyn_BINDIR = SMB_STRDUP(arg);
00195                 }
00196                 break;
00197 
00198         case DYN_SWATDIR:
00199                 if (arg) {
00200                         dyn_SWATDIR = SMB_STRDUP(arg);
00201                 }
00202                 break;
00203 
00204         case DYN_LMHOSTSFILE:
00205                 if (arg) {
00206                         pstrcpy(dyn_LMHOSTSFILE, arg);
00207                 }
00208                 break;
00209 
00210         case DYN_LIBDIR:
00211                 if (arg) {
00212                         pstrcpy(dyn_LIBDIR, arg);
00213                 }
00214                 break;
00215 
00216         case DYN_SHLIBEXT:
00217                 if (arg) {
00218                         fstrcpy(dyn_SHLIBEXT, arg);
00219                 }
00220                 break;
00221 
00222         case DYN_LOCKDIR:
00223                 if (arg) {
00224                         pstrcpy(dyn_LOCKDIR, arg);
00225                 }
00226                 break;
00227 
00228         case DYN_PIDDIR:
00229                 if (arg) {
00230                         pstrcpy(dyn_PIDDIR, arg);
00231                 }
00232                 break;
00233 
00234         case DYN_SMB_PASSWD_FILE:
00235                 if (arg) {
00236                         pstrcpy(dyn_SMB_PASSWD_FILE, arg);
00237                 }
00238                 break;
00239 
00240         case DYN_PRIVATE_DIR:
00241                 if (arg) {
00242                         pstrcpy(dyn_PRIVATE_DIR, arg);
00243                 }
00244                 break;
00245 
00246         }
00247 }
00248 
00249 const struct poptOption popt_common_dynconfig[] = {
00250 
00251         { NULL, '\0', POPT_ARG_CALLBACK, (void *)popt_dynconfig_callback },
00252 
00253         { "sbindir", '\0' , POPT_ARG_STRING, NULL, DYN_SBINDIR,
00254             "Path to sbin directory", "SBINDIR" },
00255         { "bindir", '\0' , POPT_ARG_STRING, NULL, DYN_BINDIR,
00256             "Path to bin directory", "BINDIR" },
00257         { "swatdir", '\0' , POPT_ARG_STRING, NULL, DYN_SWATDIR,
00258             "Path to SWAT installation directory", "SWATDIR" },
00259         { "lmhostsfile", '\0' , POPT_ARG_STRING, NULL, DYN_LMHOSTSFILE,
00260             "Path to lmhosts file", "LMHOSTSFILE" },
00261         { "libdir", '\0' , POPT_ARG_STRING, NULL, DYN_LIBDIR,
00262             "Path to shared library directory", "LIBDIR" },
00263         { "shlibext", '\0' , POPT_ARG_STRING, NULL, DYN_SHLIBEXT,
00264             "Shared library extension", "SHLIBEXT" },
00265         { "lockdir", '\0' , POPT_ARG_STRING, NULL, DYN_LOCKDIR,
00266             "Path to lock file directory", "LOCKDIR" },
00267         { "piddir", '\0' , POPT_ARG_STRING, NULL, DYN_PIDDIR,
00268             "Path to PID file directory", "PIDDIR" },
00269         { "smb-passwd-file", '\0' , POPT_ARG_STRING, NULL, DYN_SMB_PASSWD_FILE,
00270             "Path to smbpasswd file", "SMB_PASSWD_FILE" },
00271         { "private-dir", '\0' , POPT_ARG_STRING, NULL, DYN_PRIVATE_DIR,
00272             "Path to private data directory", "PRIVATE_DIR" },
00273 
00274         POPT_TABLEEND
00275 };
00276 
00277 /****************************************************************************
00278  * get a password from a a file or file descriptor
00279  * exit on failure
00280  * ****************************************************************************/
00281 static void get_password_file(struct user_auth_info *a)
00282 {
00283         int fd = -1;
00284         char *p;
00285         BOOL close_it = False;
00286         pstring spec;
00287         char pass[128];
00288 
00289         if ((p = getenv("PASSWD_FD")) != NULL) {
00290                 pstrcpy(spec, "descriptor ");
00291                 pstrcat(spec, p);
00292                 sscanf(p, "%d", &fd);
00293                 close_it = False;
00294         } else if ((p = getenv("PASSWD_FILE")) != NULL) {
00295                 fd = sys_open(p, O_RDONLY, 0);
00296                 pstrcpy(spec, p);
00297                 if (fd < 0) {
00298                         fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
00299                                         spec, strerror(errno));
00300                         exit(1);
00301                 }
00302                 close_it = True;
00303         }
00304 
00305         for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
00306                 p && p - pass < sizeof(pass);) {
00307                 switch (read(fd, p, 1)) {
00308                 case 1:
00309                         if (*p != '\n' && *p != '\0') {
00310                                 *++p = '\0'; /* advance p, and null-terminate pass */
00311                                 break;
00312                         }
00313                 case 0:
00314                         if (p - pass) {
00315                                 *p = '\0'; /* null-terminate it, just in case... */
00316                                 p = NULL; /* then force the loop condition to become false */
00317                                 break;
00318                         } else {
00319                                 fprintf(stderr, "Error reading password from file %s: %s\n",
00320                                                 spec, "empty password\n");
00321                                 exit(1);
00322                         }
00323 
00324                 default:
00325                         fprintf(stderr, "Error reading password from file %s: %s\n",
00326                                         spec, strerror(errno));
00327                         exit(1);
00328                 }
00329         }
00330         pstrcpy(a->password, pass);
00331         if (close_it)
00332                 close(fd);
00333 }
00334 
00335 static void get_credentials_file(const char *file, struct user_auth_info *info) 
00336 {
00337         XFILE *auth;
00338         fstring buf;
00339         uint16 len = 0;
00340         char *ptr, *val, *param;
00341 
00342         if ((auth=x_fopen(file, O_RDONLY, 0)) == NULL)
00343         {
00344                 /* fail if we can't open the credentials file */
00345                 d_printf("ERROR: Unable to open credentials file!\n");
00346                 exit(-1);
00347         }
00348 
00349         while (!x_feof(auth))
00350         {
00351                 /* get a line from the file */
00352                 if (!x_fgets(buf, sizeof(buf), auth))
00353                         continue;
00354                 len = strlen(buf);
00355 
00356                 if ((len) && (buf[len-1]=='\n'))
00357                 {
00358                         buf[len-1] = '\0';
00359                         len--;
00360                 }
00361                 if (len == 0)
00362                         continue;
00363 
00364                 /* break up the line into parameter & value.
00365                  * will need to eat a little whitespace possibly */
00366                 param = buf;
00367                 if (!(ptr = strchr_m (buf, '=')))
00368                         continue;
00369 
00370                 val = ptr+1;
00371                 *ptr = '\0';
00372 
00373                 /* eat leading white space */
00374                 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
00375                         val++;
00376 
00377                 if (strwicmp("password", param) == 0)
00378                 {
00379                         pstrcpy(info->password, val);
00380                         info->got_pass = True;
00381                 }
00382                 else if (strwicmp("username", param) == 0)
00383                         pstrcpy(info->username, val);
00384                 else if (strwicmp("domain", param) == 0)
00385                         set_global_myworkgroup(val);
00386                 memset(buf, 0, sizeof(buf));
00387         }
00388         x_fclose(auth);
00389 }
00390 
00391 /* Handle command line options:
00392  *              -U,--user
00393  *              -A,--authentication-file
00394  *              -k,--use-kerberos
00395  *              -N,--no-pass
00396  *              -S,--signing
00397  *              -P --machine-pass
00398  */
00399 
00400 
00401 static void popt_common_credentials_callback(poptContext con, 
00402                                         enum poptCallbackReason reason,
00403                                         const struct poptOption *opt,
00404                                         const char *arg, const void *data)
00405 {
00406         char *p;
00407 
00408         if (reason == POPT_CALLBACK_REASON_PRE) {
00409                 cmdline_auth_info.use_kerberos = False;
00410                 cmdline_auth_info.got_pass = False;
00411                 cmdline_auth_info.signing_state = Undefined;
00412                 pstrcpy(cmdline_auth_info.username, "GUEST");   
00413 
00414                 if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME"));
00415 
00416                 if (getenv("USER")) {
00417                         pstrcpy(cmdline_auth_info.username,getenv("USER"));
00418 
00419                         if ((p = strchr_m(cmdline_auth_info.username,'%'))) {
00420                                 *p = 0;
00421                                 pstrcpy(cmdline_auth_info.password,p+1);
00422                                 cmdline_auth_info.got_pass = True;
00423                                 memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cmdline_auth_info.password));
00424                         }
00425                 }
00426 
00427                 if (getenv("PASSWD")) {
00428                         pstrcpy(cmdline_auth_info.password,getenv("PASSWD"));
00429                         cmdline_auth_info.got_pass = True;
00430                 }
00431 
00432                 if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
00433                         get_password_file(&cmdline_auth_info);
00434                         cmdline_auth_info.got_pass = True;
00435                 }
00436 
00437                 return;
00438         }
00439 
00440         switch(opt->val) {
00441         case 'U':
00442                 {
00443                         char *lp;
00444 
00445                         pstrcpy(cmdline_auth_info.username,arg);
00446                         if ((lp=strchr_m(cmdline_auth_info.username,'%'))) {
00447                                 *lp = 0;
00448                                 pstrcpy(cmdline_auth_info.password,lp+1);
00449                                 cmdline_auth_info.got_pass = True;
00450                                 memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_auth_info.password));
00451                         }
00452                 }
00453                 break;
00454 
00455         case 'A':
00456                 get_credentials_file(arg, &cmdline_auth_info);
00457                 break;
00458 
00459         case 'k':
00460 #ifndef HAVE_KRB5
00461                 d_printf("No kerberos support compiled in\n");
00462                 exit(1);
00463 #else
00464                 cmdline_auth_info.use_kerberos = True;
00465                 cmdline_auth_info.got_pass = True;
00466 #endif
00467                 break;
00468 
00469         case 'S':
00470                 {
00471                         cmdline_auth_info.signing_state = -1;
00472                         if (strequal(arg, "off") || strequal(arg, "no") || strequal(arg, "false"))
00473                                 cmdline_auth_info.signing_state = False;
00474                         else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true") ||
00475                                         strequal(arg, "auto") )
00476                                 cmdline_auth_info.signing_state = True;
00477                         else if (strequal(arg, "force") || strequal(arg, "required") || strequal(arg, "forced"))
00478                                 cmdline_auth_info.signing_state = Required;
00479                         else {
00480                                 fprintf(stderr, "Unknown signing option %s\n", arg );
00481                                 exit(1);
00482                         }
00483                 }
00484                 break;
00485         case 'P':
00486                 {
00487                         char *opt_password = NULL;
00488                         /* it is very useful to be able to make ads queries as the
00489                            machine account for testing purposes and for domain leave */
00490                         
00491                         if (!secrets_init()) {
00492                                 d_printf("ERROR: Unable to open secrets database\n");
00493                                 exit(1);
00494                         }
00495                         
00496                         opt_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
00497                         
00498                         if (!opt_password) {
00499                                 d_printf("ERROR: Unable to fetch machine password\n");
00500                                 exit(1);
00501                         }
00502                         pstr_sprintf(cmdline_auth_info.username, "%s$", 
00503                                      global_myname());
00504                         pstrcpy(cmdline_auth_info.password,opt_password);
00505                         SAFE_FREE(opt_password);
00506 
00507                         /* machine accounts only work with kerberos */
00508                         cmdline_auth_info.use_kerberos = True;
00509                         cmdline_auth_info.got_pass = True;
00510                 }
00511                 break;
00512         }
00513 }
00514 
00515 
00516 
00517 struct poptOption popt_common_credentials[] = {
00518         { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, (void *)popt_common_credentials_callback },
00519         { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" },
00520         { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" },
00521         { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" },
00522         { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" },
00523         { "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" },
00524         {"machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" },
00525         POPT_TABLEEND
00526 };

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