popauth.c
上传用户:dayuan858
上传日期:2007-01-04
资源大小:194k
文件大小:13k
源码类别:

网络编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1997 by Qualcomm Incorporated.
  3.  */
  4. /*  */
  5. /* popauth.c - manipulate POP authorization DB */
  6. #include <config.h>
  7. #ifdef GDBM
  8. # include <gdbm.h>
  9. #else
  10. # if HAVE_NDBM_H
  11. #  include <ndbm.h>
  12. # else
  13. #  if HAVE_DBM_H
  14. #   include <dbm.h>
  15. #  endif
  16. # endif
  17. #endif
  18. #include <pwd.h>
  19. #include <stdio.h>
  20. #ifdef __STDC__
  21. #include <stdlib.h>
  22. #include <stdarg.h>
  23. #else
  24. #include <varargs.h>
  25. #endif
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <fcntl.h>
  29. #include <errno.h>
  30. #include <string.h>
  31. #ifndef HAVE_BCOPY
  32. #define bcopy(src,dest,len) (void) (memcpy(dest,src,len))
  33. #define bzero(dest,len)   (void) (memset(dest, (char)NULL, len))
  34. #define bcmp(b1,b2,n) memcmp(b1,b2,n)
  35. #endif
  36. #ifndef HAVE_INDEX
  37. # define index(s,c) strchr(s,c)
  38. # define rindex(s,c) strrchr(s,c)
  39. #endif
  40. #include <flock.h>
  41. #if HAVE_STRINGS_H
  42. #include <strings.h>
  43. #endif
  44. #if HAVE_SYS_FILE_H
  45. #include <sys/file.h>
  46. #endif
  47. #ifdef BSDI
  48. #define BSD44_DBM
  49. #endif
  50. #ifndef HAVE_STRERROR
  51. char *strerror();
  52. #endif
  53. #define UID_T uid_t
  54. static struct swit {
  55. char *name;
  56. } switches[] = {
  57. #define INITSW 0
  58.     "init", 
  59. #define LISTSW 1
  60.     "list", 
  61. #define USERSW 2
  62.     "user", 
  63. #define DELESW 3
  64.     "delete", 
  65.     NULL,
  66. };
  67. static char   *program;
  68. #ifdef __STDC__
  69. static void
  70. adios(const char *fmt, ...)
  71. #else
  72. static void
  73. adios(va_alist)
  74. va_dcl
  75. #endif
  76. {
  77. va_list ap;
  78. #ifndef __STDC__
  79. char *fmt;
  80. #endif
  81. (void) fprintf(stderr, "%s: ", program);
  82. #ifdef __STDC__
  83. va_start(ap, fmt);
  84. #else
  85. va_start(ap);
  86. fmt = va_arg(ap, char *);
  87. #endif
  88. (void) vfprintf(stderr, fmt, ap);
  89. (void) fprintf(stderr, "n");
  90. va_end(fmt);
  91. exit(1);
  92. /*NOTREACHED*/
  93. }
  94. #ifndef HAVE_STRDUP
  95. #include <stddef.h>
  96. char *
  97. strdup(str)
  98.         char *str;
  99. {
  100.     int len;
  101.     char *copy;
  102.     len = strlen(str) + 1;
  103.     if (!(copy = malloc((u_int)len)))
  104. return((char *)NULL);
  105.     bcopy(str, copy, len);
  106.     return(copy);
  107. }
  108. #endif
  109. /*
  110.  * Obscure password so a cleartext search doesn't come up with
  111.  * something interesting.
  112.  *
  113.  */
  114. char *
  115. obscure(string)
  116. char *string;
  117. {
  118. unsigned char *cp, *newstr;
  119. cp = newstr = (unsigned char *)strdup(string);
  120. while (*cp) {
  121.     *cp++ ^= 0xff;
  122. }
  123. return((char *)newstr);
  124. }
  125. /* Use GNU_PASS for longer passwords on systems that support termios */
  126. #ifndef GNU_PASS
  127. char *getpass();
  128. #else
  129. /* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
  130. This file is part of the GNU C Library.
  131. The GNU C Library is free software; you can redistribute it and/or
  132. modify it under the terms of the GNU Library General Public License as
  133. published by the Free Software Foundation; either version 2 of the
  134. License, or (at your option) any later version.
  135. The GNU C Library is distributed in the hope that it will be useful,
  136. but WITHOUT ANY WARRANTY; without even the implied warranty of
  137. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  138. Library General Public License for more details.
  139. You should have received a copy of the GNU Library General Public
  140. License along with the GNU C Library; see the file COPYING.LIB.  If
  141. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  142. Cambridge, MA 02139, USA.  */
  143. /* It is desireable to use this bit on systems that have it.
  144.    The only bit of terminal state we want to twiddle is echoing, which is
  145.    done in software; there is no need to change the state of the terminal
  146.    hardware.  */
  147. #include <stdio.h>
  148. #include <termios.h>
  149. #include <unistd.h>
  150. #ifndef TCSASOFT
  151. #define TCSASOFT 0
  152. #endif
  153. #ifdef SSIZET
  154. typedef SSIZET ssize_t;
  155. #endif
  156. char *
  157. getpass (prompt)
  158. #if defined(HPUX)
  159. char *prompt;
  160. #else
  161. const char *prompt;
  162. #endif
  163. {
  164.   FILE *in, *out;
  165.   struct termios t;
  166.   int echo_off;
  167.   static char *buf = NULL;
  168.   static size_t bufsize = 0;
  169.   ssize_t nread;
  170.   /* Try to write to and read from the terminal if we can.
  171.      If we can't open the terminal, use stderr and stdin.  */
  172.   in = fopen ("/dev/tty", "w+");
  173.   if (in == NULL)
  174.     {
  175.       in = stdin;
  176.       out = stderr;
  177.     }
  178.   else
  179.     out = in;
  180.   /* Turn echoing off if it is on now.  */
  181.   if (tcgetattr (fileno (in), &t) == 0)
  182.     {
  183.       if (t.c_lflag & ECHO)
  184. {
  185.   t.c_lflag &= ~ECHO;
  186.   echo_off = tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0;
  187.   t.c_lflag |= ECHO;
  188. }
  189.       else
  190. echo_off = 0;
  191.     }
  192.   else
  193.     echo_off = 0;
  194.   /* Write the prompt.  */
  195.   fputs (prompt, out);
  196.   fflush (out);
  197.   /* Read the password.  */
  198. #ifdef NO_GETLINE
  199.   bufsize = 256;
  200.   buf = (char *)malloc(256);
  201.   nread = (fgets(buf, (size_t)bufsize, in) == NULL) ? 1 : strlen(buf);
  202.   rewind(in);
  203.   fputc('n', out);
  204. #else
  205.   nread = __getline (&buf, &bufsize, in);
  206. #endif
  207.   if (nread < 0 && buf != NULL)
  208.     buf[0] = '';
  209.   else if (buf[nread - 1] == 'n')
  210.     /* Remove the newline.  */
  211.     buf[nread - 1] = '';
  212.   /* Restore echoing.  */
  213.   if (echo_off)
  214.     (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t);
  215.   if (in != stdin)
  216.     /* We opened the terminal; now close it.  */
  217.     fclose (in);
  218.   return buf;
  219. }
  220. #endif
  221. /* ARGSUSED */
  222. main (argc, argv)
  223. int argc;
  224. char   *argv[];
  225. {
  226.     UID_T   myuid;
  227.     int     flags,
  228.     i,
  229.     delesw = 0,
  230.     initsw = 0,
  231.     insist,
  232.     listsw = 0,
  233.     popuser = 0;
  234.     long    clock;
  235.     char   *bp,
  236.    *cp,
  237.    *usersw = NULL,
  238.     buf[100],
  239.     obuf[100];
  240.     struct  passwd *pw;
  241.     datum   key,
  242.     value;
  243. #ifdef GDBM
  244. GDBM_FILE db;
  245. char  apop_file[BUFSIZ];
  246. #else 
  247.     DBM    *db;
  248.     char    apop_dir[BUFSIZ];
  249. #ifndef BSD44_DBM
  250.     char    apop_pag[BUFSIZ];
  251. #endif
  252. #endif
  253.     int     f;
  254.     program = argv[0];
  255.     argv++;
  256.     argc--;
  257.     while (argc > 0) {
  258. cp = argv[0];
  259. if (*cp == '-') {
  260.     int i, v;
  261.     i = 0;
  262.     v = -1;
  263.     for(i = 0; switches[i].name; i++) {
  264. if(strcmp(&cp[1], switches[i].name) == 0) {
  265. v = i;
  266. break;
  267. }
  268.     }
  269.     cp++;
  270.     switch (v) {
  271. default:
  272.     adios ("-%s unknown option", cp);
  273. case INITSW:
  274.     initsw = 1, listsw = 0; delesw = 0;
  275.     break;
  276. case LISTSW:
  277.     listsw = 1, initsw = 0; delesw = 0;
  278.     break;
  279. case DELESW:
  280.     delesw = 1, initsw = 0; listsw = 0;
  281.     if (argc < 2 || argv[1][0] == '-')
  282. adios ("missing argument to %s", argv[0]);
  283.     usersw = argv[1];
  284.     argc--;
  285.     argv++;
  286.     break;
  287. case USERSW:
  288.     if (argc < 2 || argv[1][0] == '-')
  289. adios ("missing argument to %s", argv[0]);
  290.     usersw = argv[1];
  291.     argc--;
  292.     argv++;
  293.     if (delesw)
  294. fprintf(stderr, "Warning: user '%s' will now be deletedn", usersw);
  295.     break;
  296.     }
  297. }
  298. else
  299.     adios ("usage: %s [[-init]|[-list]|[-user name]|[-delete name]]", program);
  300. argc--;
  301. argv++;
  302.     }
  303. #ifndef APOP
  304.     adios ("not compiled with APOP option");
  305. #else
  306.     myuid = getuid();
  307.     if ((pw = getpwnam (POPUID)) == NULL)
  308. adios (""%s": user-id unknown", POPUID);
  309.     if (pw->pw_uid == myuid)
  310. popuser = 1;
  311.     if (myuid && !popuser && (delesw || initsw || listsw || (usersw != NULL)))
  312. adios("Only superuser or user '%s' can perform the requested function",
  313.     POPUID);
  314.     if (myuid && initsw)
  315. adios("Only superuser can init the database");
  316. #ifdef GDBM
  317. (void) strncpy(apop_file, APOP, sizeof(apop_file) - 1);
  318. apop_file[sizeof(apop_file)-1] = '';
  319. #else
  320.     (void) strncpy(apop_dir, APOP, sizeof(apop_dir) - 5);
  321. #ifdef BSD44_DBM
  322.     (void) strcat(apop_dir, ".db");
  323. #else
  324.     (void) strncpy(apop_pag, APOP, sizeof(apop_pag) - 5);
  325.     (void) strcat(apop_pag, ".pag");
  326.     (void) strcat(apop_dir, ".dir");
  327. #endif
  328. #endif
  329.     if (delesw) {
  330. if (myuid && !popuser)
  331.     adios ("Only root or %s may delete entries", POPUID);
  332. #ifdef GDBM
  333. if ((db = gdbm_open(apop_file,512,GDBM_WRITER,0,0)) == NULL)
  334. #else
  335. if ((db = dbm_open (APOP, O_RDWR, 0)) == NULL)
  336. #endif
  337.     adios ("%s: unable to open POP authorization DB", APOP);
  338. key.dsize = strlen (key.dptr = usersw) + 1;
  339. #ifdef GDBM
  340. value = gdbm_fetch(db, key);
  341. #else
  342. value = dbm_fetch(db, key);
  343. #endif
  344. if (value.dptr == NULL)
  345.     adios("User '%s' not found in apop database", usersw);
  346. #ifdef GDBM
  347. if (gdbm_delete(db,key) < 0)
  348. #else
  349. if (dbm_delete(db, key) < 0)
  350. #endif
  351.     adios("Unable to delete user '%s' from apop database", usersw);
  352. #ifdef GDBM
  353. gdbm_close (db);
  354. #else
  355. dbm_close (db);
  356. #endif
  357. exit (0);
  358.     }
  359.     if (initsw) {
  360. struct stat st;
  361. setuid(myuid);
  362. #ifdef GDBM
  363. if (stat (apop_file, &st) != -1) 
  364. #else
  365. if (stat (apop_dir, &st) != -1) 
  366. #endif
  367. {
  368.     char ibuf[30];
  369.     printf("Really initialize POP authorization DB? ");
  370.     if(fgets(ibuf, sizeof(ibuf), stdin) == NULL || ibuf[0] != 'y')
  371. exit (1);
  372. #ifdef GDBM
  373. (void) unlink (apop_file);
  374. #else
  375.     (void) unlink (apop_dir);
  376. # ifndef BSD44_DBM
  377.     (void) unlink (apop_pag);
  378. # endif
  379. #endif
  380. }
  381. #ifdef GDBM
  382. if ((db = gdbm_open (apop_file, 512, GDBM_WRCREAT, 0600, 0)) == NULL)
  383.     adios ("unable to create POP authorization DB: %s", 
  384.      strerror(errno));
  385. gdbm_close (db);
  386. if (chown (apop_file, pw->pw_uid, pw->pw_gid) == -1)
  387.     adios ("error setting ownership of POP authorization for %s : %s", 
  388. apop_file, strerror(errno));
  389. #else
  390. if ((db = dbm_open (APOP, O_RDWR | O_CREAT, 0600)) == NULL)
  391.     adios ("unable to create POP authorization DB: %s", 
  392.      strerror(errno));
  393. dbm_close (db);
  394. if (chown (apop_dir, pw->pw_uid, pw->pw_gid) == -1 
  395. #ifndef BSD44_DBM
  396.  || chown (apop_pag, pw->pw_uid, pw->pw_gid) == -1
  397. #endif
  398.     )
  399.     adios ("error setting ownership of POP authorization DB: %s", 
  400. strerror(errno));
  401. #endif
  402. exit (0);
  403.     }
  404. #ifdef GDBM
  405.     if ((db = gdbm_open (apop_file, 512, GDBM_READER, 0, 0)) == NULL)
  406. #else
  407.     if ((db = dbm_open (APOP, O_RDONLY, 0)) == NULL)
  408. #endif
  409. adios ("unable to open POP authorization DB: %s", strerror(errno));
  410. #ifdef GDBM
  411.     if ((f = open (apop_file, listsw ? O_RDONLY : O_RDWR)) == -1)
  412. adios ("%s: unable to open POP authorization DB", apop_file);
  413.     if (flock (f, LOCK_SH) == -1)
  414. adios ("%s: unable to lock POP authorization DB", apop_file);
  415. #else
  416.     if ((f = open (apop_dir, listsw ? O_RDONLY : O_RDWR)) == -1)
  417. adios ("%s: unable to open POP authorization DB", apop_dir);
  418.     if (flock (f, LOCK_SH) == -1)
  419. adios ("%s: unable to lock POP authorization DB", apop_dir);
  420. #endif
  421.     if (listsw) {
  422. if (usersw) {
  423.     key.dsize = strlen (key.dptr = usersw) + 1;
  424. #ifdef GDBM
  425.     value = gdbm_fetch (db, key);
  426. #else
  427.     value = dbm_fetch (db, key);
  428. #endif
  429.     if (value.dptr == NULL)
  430. adios ("no such entry in POP authorization DB");
  431.     printf ("%sn", key.dptr);
  432. }
  433. else
  434. #ifdef GDBM
  435.     for (key = gdbm_firstkey (db); key.dptr; key = gdbm_nextkey (db,key)) 
  436. #else
  437.     for (key = dbm_firstkey (db); key.dptr; key = dbm_nextkey (db)) 
  438. #endif
  439. {
  440. printf ("%s", key.dptr);
  441. #ifdef GDBM
  442. value = gdbm_fetch (db, key);
  443. #else
  444. value = dbm_fetch (db, key);
  445. #endif
  446. if (value.dptr == NULL)
  447.     printf (" - no information?!?n");
  448. else {
  449.     printf ("n");
  450. }
  451.     }
  452. #ifdef GDBM
  453. gdbm_close (db);
  454. #else
  455. dbm_close (db);
  456. #endif
  457. exit (0);
  458.     }
  459.     if (usersw == NULL) {
  460. if ((pw = getpwuid(myuid)) == NULL)
  461.     adios("Sorry, don't know who uid %d is.", myuid);
  462. usersw = pw->pw_name;
  463.     } else {
  464. if ((pw = getpwnam(usersw)) == NULL)
  465.     adios("Sorry, don't know who uid %s is.", usersw);
  466. usersw = pw->pw_name;
  467.     }
  468.     fprintf (stderr, "Changing POP password for %s.n", usersw);
  469.     key.dsize = strlen (key.dptr = usersw) + 1;
  470. #ifdef GDBM
  471.     value = gdbm_fetch (db, key);
  472. #else
  473.     value = dbm_fetch (db, key);
  474. #endif
  475.     if (myuid && !popuser && value.dptr != NULL) {
  476. if (((i = strlen(strncpy(obuf, getpass("Old password:"), sizeof(obuf)))) == 0) ||
  477. ((value.dsize - 1) != i) ||
  478. (strncmp(obuf, value.dptr, i) &&
  479.      strncmp(obuf, obscure(value.dptr), i))) {
  480.     adios("Sorry, password entered incorrectlyn");
  481. }
  482.     }
  483. #ifdef GDBM
  484.     gdbm_close (db);
  485. #else
  486. dbm_close (db);
  487. #endif
  488. #ifdef lint
  489.     flags = 0;
  490. #endif /* lint */
  491.     for (insist = 0; insist < 2; insist++) {
  492. int i;
  493. char    c;
  494. if (insist)
  495.     printf ("Please use %s.n",
  496.     flags == 1 ? "at least one non-numeric character"
  497.     : "a longer password");
  498. if (((i = strlen(strncpy(buf, getpass("New password:"), sizeof(buf)))) == 0) ||
  499.       !strncmp(buf, obuf, i)) {
  500.     fprintf (stderr, "Password unchanged.n");
  501.     exit (1);
  502. }
  503. flags = 0;
  504. for (cp = buf; c = *cp++;)
  505.     if (c >= 'a' && c <= 'z')
  506. flags |= 2;
  507.     else
  508. if (c >= 'A' && c <= 'Z')
  509.     flags |= 4;
  510. else
  511.     if (c >= '0' && c <= '9')
  512. flags |= 1;
  513.     else
  514. flags |= 8;
  515. if ((flags >= 7 && i >= 4)
  516. || ((flags == 2 || flags == 4) && i >= 6)
  517. || ((flags == 3 || flags == 5 || flags == 6) && i >= 5))
  518.     break;
  519.     }
  520.     if (strcmp(buf, getpass("Retype new password:"))) {
  521. fprintf (stderr, "Mismatch - password unchanged.n");
  522. exit (1);
  523.     }
  524. #ifdef GDBM
  525. if ((db = gdbm_open(apop_file, 512, GDBM_WRITER, 0, 0)) == NULL)
  526. #else
  527.     if ((db = dbm_open(APOP, O_RDWR, 0)) == NULL)
  528. #endif
  529. adios("%s: unable to open POP authorization DB", APOP);
  530.     if (flock(f, LOCK_EX) == -1)
  531. adios("%s: unable to lock POP authorization DB", 
  532. #ifdef GDBM
  533. apop_file
  534. #else
  535. apop_dir
  536. #endif
  537. );
  538.     key.dsize = strlen (key.dptr = usersw) + 1;
  539.     value.dptr = obscure(buf);
  540.     value.dsize = strlen(value.dptr) + 1;
  541. #ifdef GDBM
  542.     if (gdbm_store (db, key, value, GDBM_REPLACE))
  543. adios ("POP authorization DB may be corrupt?!?");
  544.     gdbm_close (db);
  545. #else
  546.     if (dbm_store (db, key, value, DBM_REPLACE))
  547. adios ("POP authorization DB may be corrupt?!?");
  548.     dbm_close (db);
  549. #endif
  550. #endif
  551.     exit (0);
  552.     /* NOTREACHED */
  553. }
  554. #ifndef HAVE_STRERROR
  555. char *
  556. strerror(e)
  557. int e;
  558. {
  559. extern char *sys_errlist[];
  560. extern int sys_nerr;
  561. if(e < sys_nerr)
  562. return(sys_errlist[e]);
  563. else
  564. return("unknown error");
  565. }
  566. #endif