lib/username.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Username handling
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    Copyright (C) Jeremy Allison 1997-2001.
00006    
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011    
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016    
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 */
00021 
00022 #include "includes.h"
00023 
00024 /* internal functions */
00025 static struct passwd *uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
00026                                                 struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
00027                                                 int N);
00028 static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx, int offset,
00029                                                  struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
00030                                                  int N);
00031 
00032 /****************************************************************************
00033  Get a users home directory.
00034 ****************************************************************************/
00035 
00036 char *get_user_home_dir(const char *user)
00037 {
00038         static struct passwd *pass;
00039 
00040         /* Ensure the user exists. */
00041 
00042         pass = Get_Pwnam(user);
00043 
00044         if (!pass)
00045                 return(NULL);
00046         /* Return home directory from struct passwd. */
00047 
00048         return(pass->pw_dir);      
00049 }
00050 
00051 /****************************************************************************
00052  * A wrapper for sys_getpwnam().  The following variations are tried:
00053  *   - as transmitted
00054  *   - in all lower case if this differs from transmitted
00055  *   - in all upper case if this differs from transmitted
00056  *   - using lp_usernamelevel() for permutations.
00057 ****************************************************************************/
00058 
00059 static struct passwd *Get_Pwnam_ret = NULL;
00060 
00061 static struct passwd *Get_Pwnam_internals(TALLOC_CTX *mem_ctx,
00062                                           const char *user, char *user2)
00063 {
00064         struct passwd *ret = NULL;
00065 
00066         if (!user2 || !(*user2))
00067                 return(NULL);
00068 
00069         if (!user || !(*user))
00070                 return(NULL);
00071 
00072         /* Try in all lower case first as this is the most 
00073            common case on UNIX systems */
00074         strlower_m(user2);
00075         DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2));
00076         ret = getpwnam_alloc(mem_ctx, user2);
00077         if(ret)
00078                 goto done;
00079 
00080         /* Try as given, if username wasn't originally lowercase */
00081         if(strcmp(user, user2) != 0) {
00082                 DEBUG(5,("Trying _Get_Pwnam(), username as given is %s\n",
00083                          user));
00084                 ret = getpwnam_alloc(mem_ctx, user);
00085                 if(ret)
00086                         goto done;
00087         }
00088 
00089         /* Try as uppercase, if username wasn't originally uppercase */
00090         strupper_m(user2);
00091         if(strcmp(user, user2) != 0) {
00092                 DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n",
00093                          user2));
00094                 ret = getpwnam_alloc(mem_ctx, user2);
00095                 if(ret)
00096                         goto done;
00097         }
00098 
00099         /* Try all combinations up to usernamelevel */
00100         strlower_m(user2);
00101         DEBUG(5,("Checking combinations of %d uppercase letters in %s\n",
00102                  lp_usernamelevel(), user2));
00103         ret = uname_string_combinations(user2, mem_ctx, getpwnam_alloc,
00104                                         lp_usernamelevel());
00105 
00106 done:
00107         DEBUG(5,("Get_Pwnam_internals %s find user [%s]!\n",ret ?
00108                  "did":"didn't", user));
00109 
00110         return ret;
00111 }
00112 
00113 /****************************************************************************
00114  Get_Pwnam wrapper without modification.
00115   NOTE: This with NOT modify 'user'! 
00116   This will return an allocated structure
00117 ****************************************************************************/
00118 
00119 struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const char *user)
00120 {
00121         fstring user2;
00122         struct passwd *ret;
00123 
00124         if ( *user == '\0' ) {
00125                 DEBUG(10,("Get_Pwnam: empty username!\n"));
00126                 return NULL;
00127         }
00128 
00129         fstrcpy(user2, user);
00130 
00131         DEBUG(5,("Finding user %s\n", user));
00132 
00133         ret = Get_Pwnam_internals(mem_ctx, user, user2);
00134         
00135         return ret;  
00136 }
00137 
00138 /****************************************************************************
00139  Get_Pwnam wrapper without modification.
00140   NOTE: This with NOT modify 'user'! 
00141 ****************************************************************************/
00142 
00143 struct passwd *Get_Pwnam(const char *user)
00144 {
00145         struct passwd *ret;
00146 
00147         ret = Get_Pwnam_alloc(NULL, user);
00148         
00149         /* This call used to just return the 'passwd' static buffer.
00150            This could then have accidental reuse implications, so 
00151            we now malloc a copy, and free it in the next use.
00152 
00153            This should cause the (ab)user to segfault if it 
00154            uses an old struct. 
00155            
00156            This is better than useing the wrong data in security
00157            critical operations.
00158 
00159            The real fix is to make the callers free the returned 
00160            malloc'ed data.
00161         */
00162 
00163         if (Get_Pwnam_ret) {
00164                 TALLOC_FREE(Get_Pwnam_ret);
00165         }
00166         
00167         Get_Pwnam_ret = ret;
00168 
00169         return ret;  
00170 }
00171 
00172 /* The functions below have been taken from password.c and slightly modified */
00173 /****************************************************************************
00174  Apply a function to upper/lower case combinations
00175  of a string and return true if one of them returns true.
00176  Try all combinations with N uppercase letters.
00177  offset is the first char to try and change (start with 0)
00178  it assumes the string starts lowercased
00179 ****************************************************************************/
00180 
00181 static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx,
00182                                                  int offset,
00183                                                  struct passwd *(*fn)(TALLOC_CTX *mem_ctx, const char *),
00184                                                  int N)
00185 {
00186         ssize_t len = (ssize_t)strlen(s);
00187         int i;
00188         struct passwd *ret;
00189 
00190         if (N <= 0 || offset >= len)
00191                 return(fn(mem_ctx, s));
00192 
00193         for (i=offset;i<(len-(N-1));i++) {
00194                 char c = s[i];
00195                 if (!islower_ascii((int)c))
00196                         continue;
00197                 s[i] = toupper_ascii(c);
00198                 ret = uname_string_combinations2(s, mem_ctx, i+1, fn, N-1);
00199                 if(ret)
00200                         return(ret);
00201                 s[i] = c;
00202         }
00203         return(NULL);
00204 }
00205 
00206 /****************************************************************************
00207  Apply a function to upper/lower case combinations
00208  of a string and return true if one of them returns true.
00209  Try all combinations with up to N uppercase letters.
00210  offset is the first char to try and change (start with 0)
00211  it assumes the string starts lowercased
00212 ****************************************************************************/
00213 
00214 static struct passwd * uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
00215                                                  struct passwd * (*fn)(TALLOC_CTX *mem_ctx, const char *),
00216                                                  int N)
00217 {
00218         int n;
00219         struct passwd *ret;
00220 
00221         for (n=1;n<=N;n++) {
00222                 ret = uname_string_combinations2(s,mem_ctx,0,fn,n);
00223                 if(ret)
00224                         return(ret);
00225         }  
00226         return(NULL);
00227 }
00228 

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