PageRenderTime 59ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/apps/samba-2.0.10/source/lib/username.c

https://bitbucket.org/jonathanxavier/snake-os
C | 426 lines | 256 code | 73 blank | 97 comment | 79 complexity | 5ccb83812247c8ac851ed450f60b1592 MD5 | raw file
Possible License(s): AGPL-1.0, CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, 0BSD, BSD-3-Clause, GPL-3.0
  1. /*
  2. Unix SMB/Netbios implementation.
  3. Version 1.9.
  4. Username handling
  5. Copyright (C) Andrew Tridgell 1992-1998
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #include "includes.h"
  19. extern int DEBUGLEVEL;
  20. /* internal functions */
  21. static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (char *), int N);
  22. static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (char *), int N);
  23. /****************************************************************************
  24. Get a users home directory.
  25. ****************************************************************************/
  26. char *get_user_home_dir(char *user)
  27. {
  28. static struct passwd *pass;
  29. pass = Get_Pwnam(user, False);
  30. if (!pass) return(NULL);
  31. return(pass->pw_dir);
  32. }
  33. /*******************************************************************
  34. Map a username from a dos name to a unix name by looking in the username
  35. map. Note that this modifies the name in place.
  36. This is the main function that should be called *once* on
  37. any incoming or new username - in order to canonicalize the name.
  38. This is being done to de-couple the case conversions from the user mapping
  39. function. Previously, the map_username was being called
  40. every time Get_Pwnam was called.
  41. Returns True if username was changed, false otherwise.
  42. ********************************************************************/
  43. BOOL map_username(char *user)
  44. {
  45. static BOOL initialised=False;
  46. static fstring last_from,last_to;
  47. FILE *f;
  48. char *mapfile = lp_username_map();
  49. char *s;
  50. pstring buf;
  51. BOOL mapped_user = False;
  52. if (!*user)
  53. return False;
  54. if (!*mapfile)
  55. return False;
  56. if (!initialised) {
  57. *last_from = *last_to = 0;
  58. initialised = True;
  59. }
  60. if (strequal(user,last_to))
  61. return False;
  62. if (strequal(user,last_from)) {
  63. DEBUG(3,("Mapped user %s to %s\n",user,last_to));
  64. fstrcpy(user,last_to);
  65. return True;
  66. }
  67. f = sys_fopen(mapfile,"r");
  68. if (!f) {
  69. DEBUG(0,("can't open username map %s\n",mapfile));
  70. return False;
  71. }
  72. DEBUG(4,("Scanning username map %s\n",mapfile));
  73. while((s=fgets_slash(buf,sizeof(buf),f))!=NULL) {
  74. char *unixname = s;
  75. char *dosname = strchr(unixname,'=');
  76. BOOL return_if_mapped = False;
  77. if (!dosname)
  78. continue;
  79. *dosname++ = 0;
  80. while (isspace(*unixname))
  81. unixname++;
  82. if ('!' == *unixname) {
  83. return_if_mapped = True;
  84. unixname++;
  85. while (*unixname && isspace(*unixname))
  86. unixname++;
  87. }
  88. if (!*unixname || strchr("#;",*unixname))
  89. continue;
  90. {
  91. int l = strlen(unixname);
  92. while (l && isspace(unixname[l-1])) {
  93. unixname[l-1] = 0;
  94. l--;
  95. }
  96. }
  97. if (strchr(dosname,'*') || user_in_list(user,dosname)) {
  98. DEBUG(3,("Mapped user %s to %s\n",user,unixname));
  99. mapped_user = True;
  100. fstrcpy(last_from,user);
  101. sscanf(unixname,"%s",user);
  102. fstrcpy(last_to,user);
  103. if(return_if_mapped) {
  104. fclose(f);
  105. return True;
  106. }
  107. }
  108. }
  109. fclose(f);
  110. /*
  111. * Setup the last_from and last_to as an optimization so
  112. * that we don't scan the file again for the same user.
  113. */
  114. fstrcpy(last_from,user);
  115. fstrcpy(last_to,user);
  116. return mapped_user;
  117. }
  118. /****************************************************************************
  119. Get_Pwnam wrapper
  120. ****************************************************************************/
  121. static struct passwd *_Get_Pwnam(char *s)
  122. {
  123. struct passwd *ret;
  124. ret = sys_getpwnam(s);
  125. if (ret) {
  126. #ifdef HAVE_GETPWANAM
  127. struct passwd_adjunct *pwret;
  128. pwret = getpwanam(s);
  129. if (pwret && pwret->pwa_passwd) {
  130. pstrcpy(ret->pw_passwd,pwret->pwa_passwd);
  131. }
  132. #endif
  133. }
  134. return(ret);
  135. }
  136. /****************************************************************************
  137. A wrapper for getpwnam() that tries with all lower and all upper case
  138. if the initial name fails. Also tried with first letter capitalised
  139. Note that this can change user!
  140. ****************************************************************************/
  141. struct passwd *Get_Pwnam(char *user,BOOL allow_change)
  142. {
  143. fstring user2;
  144. int last_char;
  145. int usernamelevel = lp_usernamelevel();
  146. struct passwd *ret;
  147. if (!user || !(*user))
  148. return(NULL);
  149. StrnCpy(user2,user,sizeof(user2)-1);
  150. if (!allow_change) {
  151. user = &user2[0];
  152. }
  153. ret = _Get_Pwnam(user);
  154. if (ret)
  155. return(ret);
  156. strlower(user);
  157. ret = _Get_Pwnam(user);
  158. if (ret)
  159. return(ret);
  160. strupper(user);
  161. ret = _Get_Pwnam(user);
  162. if (ret)
  163. return(ret);
  164. /* Try with first letter capitalised. */
  165. if (strlen(user) > 1)
  166. strlower(user+1);
  167. ret = _Get_Pwnam(user);
  168. if (ret)
  169. return(ret);
  170. /* try with last letter capitalised */
  171. strlower(user);
  172. last_char = strlen(user)-1;
  173. user[last_char] = toupper(user[last_char]);
  174. ret = _Get_Pwnam(user);
  175. if (ret)
  176. return(ret);
  177. /* Try all combinations up to usernamelevel. */
  178. strlower(user);
  179. ret = uname_string_combinations(user, _Get_Pwnam, usernamelevel);
  180. if (ret)
  181. return(ret);
  182. if (allow_change)
  183. fstrcpy(user,user2);
  184. return(NULL);
  185. }
  186. /****************************************************************************
  187. Check if a user is in a netgroup user list.
  188. ****************************************************************************/
  189. static BOOL user_in_netgroup_list(char *user,char *ngname)
  190. {
  191. #ifdef HAVE_NETGROUP
  192. static char *mydomain = NULL;
  193. if (mydomain == NULL)
  194. yp_get_default_domain(&mydomain);
  195. if(mydomain == NULL) {
  196. DEBUG(5,("Unable to get default yp domain\n"));
  197. } else {
  198. DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
  199. user, mydomain, ngname));
  200. DEBUG(5,("innetgr is %s\n",
  201. innetgr(ngname, NULL, user, mydomain)
  202. ? "TRUE" : "FALSE"));
  203. if (innetgr(ngname, NULL, user, mydomain))
  204. return (True);
  205. }
  206. #endif /* HAVE_NETGROUP */
  207. return False;
  208. }
  209. /****************************************************************************
  210. Check if a user is in a UNIX user list.
  211. ****************************************************************************/
  212. static BOOL user_in_group_list(char *user,char *gname)
  213. {
  214. #ifdef HAVE_GETGRENT
  215. struct group *gptr;
  216. char **member;
  217. struct passwd *pass = Get_Pwnam(user,False);
  218. if (pass) {
  219. gptr = getgrgid(pass->pw_gid);
  220. if (gptr && strequal(gptr->gr_name,gname))
  221. return(True);
  222. }
  223. setgrent();
  224. while ((gptr = (struct group *)getgrent())) {
  225. if (!strequal(gptr->gr_name,gname))
  226. continue;
  227. member = gptr->gr_mem;
  228. while (member && *member) {
  229. if (strequal(*member,user)) {
  230. endgrent();
  231. return(True);
  232. }
  233. member++;
  234. }
  235. }
  236. endgrent();
  237. #endif /* HAVE_GETGRNAM */
  238. return False;
  239. }
  240. /****************************************************************************
  241. Check if a user is in a user list - can check combinations of UNIX
  242. and netgroup lists.
  243. ****************************************************************************/
  244. BOOL user_in_list(char *user,char *list)
  245. {
  246. pstring tok;
  247. char *p=list;
  248. while (next_token(&p,tok,LIST_SEP, sizeof(tok))) {
  249. /*
  250. * Check raw username.
  251. */
  252. if (strequal(user,tok))
  253. return(True);
  254. /*
  255. * Now check to see if any combination
  256. * of UNIX and netgroups has been specified.
  257. */
  258. if(*tok == '@') {
  259. /*
  260. * Old behaviour. Check netgroup list
  261. * followed by UNIX list.
  262. */
  263. if(user_in_netgroup_list(user,&tok[1]))
  264. return True;
  265. if(user_in_group_list(user,&tok[1]))
  266. return True;
  267. } else if (*tok == '+') {
  268. if(tok[1] == '&') {
  269. /*
  270. * Search UNIX list followed by netgroup.
  271. */
  272. if(user_in_group_list(user,&tok[2]))
  273. return True;
  274. if(user_in_netgroup_list(user,&tok[2]))
  275. return True;
  276. } else {
  277. /*
  278. * Just search UNIX list.
  279. */
  280. if(user_in_group_list(user,&tok[1]))
  281. return True;
  282. }
  283. } else if (*tok == '&') {
  284. if(tok[1] == '+') {
  285. /*
  286. * Search netgroup list followed by UNIX list.
  287. */
  288. if(user_in_netgroup_list(user,&tok[2]))
  289. return True;
  290. if(user_in_group_list(user,&tok[2]))
  291. return True;
  292. } else {
  293. /*
  294. * Just search netgroup list.
  295. */
  296. if(user_in_netgroup_list(user,&tok[1]))
  297. return True;
  298. }
  299. }
  300. }
  301. return(False);
  302. }
  303. /* The functions below have been taken from password.c and slightly modified */
  304. /****************************************************************************
  305. Apply a function to upper/lower case combinations
  306. of a string and return true if one of them returns true.
  307. Try all combinations with N uppercase letters.
  308. offset is the first char to try and change (start with 0)
  309. it assumes the string starts lowercased
  310. ****************************************************************************/
  311. static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(char *),int N)
  312. {
  313. ssize_t len = (ssize_t)strlen(s);
  314. int i;
  315. struct passwd *ret;
  316. #ifdef PASSWORD_LENGTH
  317. len = MIN(len,PASSWORD_LENGTH);
  318. #endif
  319. if (N <= 0 || offset >= len)
  320. return(fn(s));
  321. for (i=offset;i<(len-(N-1));i++) {
  322. char c = s[i];
  323. if (!islower(c))
  324. continue;
  325. s[i] = toupper(c);
  326. ret = uname_string_combinations2(s,i+1,fn,N-1);
  327. if(ret)
  328. return(ret);
  329. s[i] = c;
  330. }
  331. return(NULL);
  332. }
  333. /****************************************************************************
  334. Apply a function to upper/lower case combinations
  335. of a string and return true if one of them returns true.
  336. Try all combinations with up to N uppercase letters.
  337. offset is the first char to try and change (start with 0)
  338. it assumes the string starts lowercased
  339. ****************************************************************************/
  340. static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(char *),int N)
  341. {
  342. int n;
  343. struct passwd *ret;
  344. for (n=1;n<=N;n++) {
  345. ret = uname_string_combinations2(s,0,fn,n);
  346. if(ret)
  347. return(ret);
  348. }
  349. return(NULL);
  350. }