Advertisement
Guest User

Untitled

a guest
Apr 22nd, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 22.01 KB | None | 0 0
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2.  * contributor license agreements.  See the NOTICE file distributed with
  3.  * this work for additional information regarding copyright ownership.
  4.  * The ASF licenses this file to You under the Apache License, Version 2.0
  5.  * (the "License"); you may not use this file except in compliance with
  6.  * the License.  You may obtain a copy of the License at
  7.  *
  8.  *     http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16.  
  17. /******************************************************************************
  18.  ******************************************************************************
  19.  * NOTE! This program is not safe as a setuid executable!  Do not make it
  20.  * setuid!
  21.  ******************************************************************************
  22.  *****************************************************************************/
  23. /*
  24.  * htpasswd.c: simple program for manipulating password file for
  25.  * the Apache HTTP server
  26.  *
  27.  * Originally by Rob McCool
  28.  *
  29.  * Exit values:
  30.  *  0: Success
  31.  *  1: Failure; file access/permission problem
  32.  *  2: Failure; command line syntax problem (usage message issued)
  33.  *  3: Failure; password verification failure
  34.  *  4: Failure; operation interrupted (such as with CTRL/C)
  35.  *  5: Failure; buffer would overflow (username, filename, or computed
  36.  *     record too long)
  37.  *  6: Failure; username contains illegal or reserved characters
  38.  *  7: Failure; file is not a valid htpasswd file
  39.  */
  40.  
  41. #include "apr.h"
  42. #include "apr_lib.h"
  43. #include "apr_strings.h"
  44. #include "apr_errno.h"
  45. #include "apr_file_io.h"
  46. #include "apr_general.h"
  47. #include "apr_signal.h"
  48.  
  49. #if APR_HAVE_STDIO_H
  50. #include <stdio.h>
  51. #endif
  52.  
  53. #include "apr_md5.h"
  54. #include "apr_sha1.h"
  55. #include <time.h>
  56.  
  57. #if APR_HAVE_CRYPT_H
  58. #include <crypt.h>
  59. #endif
  60. #if APR_HAVE_STDLIB_H
  61. #include <stdlib.h>
  62. #endif
  63. #if APR_HAVE_STRING_H
  64. #include <string.h>
  65. #endif
  66. #if APR_HAVE_UNISTD_H
  67. #include <unistd.h>
  68. #endif
  69.  
  70. #ifdef WIN32
  71. #include <conio.h>
  72. #define unlink _unlink
  73. #endif
  74.  
  75. #if !APR_CHARSET_EBCDIC
  76. #define LF 10
  77. #define CR 13
  78. #else /*APR_CHARSET_EBCDIC*/
  79. #define LF '\n'
  80. #define CR '\r'
  81. #endif /*APR_CHARSET_EBCDIC*/
  82.  
  83. #define MAX_STRING_LEN 256
  84. #define ALG_PLAIN 0
  85. #define ALG_CRYPT 1
  86. #define ALG_APMD5 2
  87. #define ALG_APSHA 3
  88.  
  89. #define ERR_FILEPERM 1
  90. #define ERR_SYNTAX 2
  91. #define ERR_PWMISMATCH 3
  92. #define ERR_INTERRUPTED 4
  93. #define ERR_OVERFLOW 5
  94. #define ERR_BADUSER 6
  95. #define ERR_INVALID 7
  96.  
  97. #define APHTP_NEWFILE        1
  98. #define APHTP_NOFILE         2
  99. #define APHTP_NONINTERACTIVE 4
  100. #define APHTP_DELUSER        8
  101.  
  102. apr_file_t *errfile;
  103. apr_file_t *ftemp = NULL;
  104.  
  105. #define NL APR_EOL_STR
  106.  
  107. static void to64(char *s, unsigned long v, int n) {
  108.     static unsigned char itoa64[] =         /* 0 ... 63 => ASCII - 64 */
  109.             "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  110.  
  111.     while (--n >= 0) {
  112.         *s++ = itoa64[v & 0x3f];
  113.         v >>= 6;
  114.     }
  115. }
  116.  
  117. static void generate_salt(char *s, size_t size) {
  118.     static unsigned char tbl[] =
  119.             "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  120.     size_t i;
  121.     for (i = 0; i < size; ++i) {
  122.         int idx = (int) (64.0 * rand() / (RAND_MAX + 1.0));
  123.         s[i] = tbl[idx];
  124.     }
  125. }
  126.  
  127. static apr_status_t seed_rand(void) {
  128.     int seed = 0;
  129.     apr_status_t rv;
  130.     rv = apr_generate_random_bytes((unsigned char *) &seed, sizeof(seed));
  131.     if (rv) {
  132.         apr_file_printf(errfile, "Unable to generate random bytes: %pm"
  133.         NL, &rv);
  134.         return rv;
  135.     }
  136.     srand(seed);
  137.     return rv;
  138. }
  139.  
  140. static void putline(apr_file_t *f, const char *l) {
  141.     apr_status_t rc;
  142.     rc = apr_file_puts(l, f);
  143.     if (rc != APR_SUCCESS) {
  144.         char errstr[MAX_STRING_LEN];
  145.         apr_strerror(rc, errstr, MAX_STRING_LEN);
  146.         apr_file_printf(errfile, "Error writing temp file: %s"
  147.         NL, errstr);
  148.         apr_file_close(f);
  149.         exit(ERR_FILEPERM);
  150.     }
  151. }
  152.  
  153. static int proverkaParolya(char *passwd) {
  154.     int condition = 0, i, x1, x2, x3, x4;
  155.     char A[100] = {0};
  156.     while (condition != 4) {
  157.         printf("\n\nEnter password:");
  158.         scanf("%s", A);
  159.         x1 = 0;
  160.         x2 = 0;
  161.         x3 = 0;
  162.         x4 = 0;
  163.         condition = 0;
  164.         for (i = 0; A[i] != '\0'; i++) {
  165.             if (A[i] >= 65 && A[i] <= 90)
  166.                 x1 = 1;
  167.             if (A[i] >= 97 && A[i] <= 122)
  168.                 x2 = 1;
  169.             if (A[i] >= 48 && A[i] <= 57)
  170.                 x3 = 1;
  171.             if (A[i] == 95)
  172.                 x4 = 1;
  173.         }
  174.         if (x4 == 0) {
  175.             printf("\nPassword must have at least special symbol.\n");
  176.             return 0;
  177.         } if (x1 == 0) {
  178.             printf("\nPassword must have at least one capital letter.\n");
  179.             return 0;
  180.         } if (x2 == 0) {
  181.             printf("\nPassword must have at least one lowercase letter.\n");
  182.             return 0;
  183.         } if (x3 == 0) {
  184.             printf("\nPassword must have at least one numeral.\n");
  185.             return 0;
  186.         } if (i < 10) {
  187.             condition = 0;
  188.             printf("\nPassword must be 10 characters in length.");
  189.             return 0;
  190.         }
  191.         condition = x1 + x2 + x3 + x4;
  192.     }
  193.     return 1;
  194. }
  195.  
  196. /*
  197.  * Make a password record from the given information.  A zero return
  198.  * indicates success; failure means that the output buffer contains an
  199.  * error message instead.
  200.  */
  201. static int mkrecord(char *user, char *record, apr_size_t rlen, char *passwd,
  202.                     int alg) {
  203.     char *pw;
  204.     char cpw[120];
  205.     char pwin[MAX_STRING_LEN];
  206.     char pwv[MAX_STRING_LEN];
  207.     char salt[9];
  208.     apr_size_t bufsize;
  209.  
  210.     if (passwd != NULL) {
  211.         pw = passwd;
  212.     } else {
  213.         metka:
  214.         bufsize = sizeof(pwin);
  215.         if (apr_password_get("New password: ", pwin, &bufsize) != 0) {
  216.             apr_snprintf(record, (rlen - 1), "password too long (>%"
  217.             APR_SIZE_T_FMT
  218.             ")", sizeof(pwin) - 1);
  219.             return ERR_OVERFLOW;
  220.         }
  221.         bufsize = sizeof(pwv);
  222.         apr_password_get("Re-type new password: ", pwv, &bufsize);
  223.         if (strcmp(pwin, pwv) != 0) {
  224.             apr_cpystrn(record, "password verification error", (rlen - 1));
  225.             return ERR_PWMISMATCH;
  226.         }
  227.         pw = pwin;
  228.         memset(pwv, '\0', sizeof(pwin));
  229.     }
  230.     if (!proverkaParolya(pw)) {
  231.         goto metka;
  232.     }
  233.     switch (alg) {
  234.  
  235.         case ALG_APSHA:
  236.             /* XXX cpw >= 28 + strlen(sha1) chars - fixed len SHA */
  237.             apr_sha1_base64(pw, strlen(pw), cpw);
  238.             break;
  239.  
  240.         case ALG_APMD5:
  241.             if (seed_rand()) {
  242.                 break;
  243.             }
  244.             generate_salt(&salt[0], 8);
  245.             salt[8] = '\0';
  246.  
  247.             apr_md5_encode((const char *) pw, (const char *) salt,
  248.                            cpw, sizeof(cpw));
  249.             break;
  250.  
  251.         case ALG_PLAIN:
  252.             /* XXX this len limitation is not in sync with any HTTPd len. */
  253.             apr_cpystrn(cpw, pw, sizeof(cpw));
  254.             break;
  255.  
  256. #if (!(defined(WIN32) || defined(NETWARE)))
  257.         case ALG_CRYPT:
  258.         default:
  259.             if (seed_rand()) {
  260.                 break;
  261.             }
  262.             to64(&salt[0], rand(), 8);
  263.             salt[8] = '\0';
  264.  
  265.             apr_cpystrn(cpw, crypt(pw, salt), sizeof(cpw) - 1);
  266.             if (strlen(pw) > 8) {
  267.                 char *truncpw = strdup(pw);
  268.                 truncpw[8] = '\0';
  269.                 if (!strcmp(cpw, crypt(truncpw, salt))) {
  270.                     apr_file_printf(errfile, "Warning: Password truncated to 8 characters "
  271.                                              "by CRYPT algorithm."
  272.                     NL);
  273.                 }
  274.                 free(truncpw);
  275.             }
  276.             break;
  277. #endif
  278.     }
  279.     memset(pw, '\0', strlen(pw));
  280.  
  281.     /*
  282.      * Check to see if the buffer is large enough to hold the username,
  283.      * hash, and delimiters.
  284.      */
  285.     if ((strlen(user) + 1 + strlen(cpw)) > (rlen - 1)) {
  286.         apr_cpystrn(record, "resultant record too long", (rlen - 1));
  287.         return ERR_OVERFLOW;
  288.     }
  289.     strcpy(record, user);
  290.     strcat(record, ":");
  291.     strcat(record, cpw);
  292.     strcat(record, "\n");
  293.     return 0;
  294. }
  295.  
  296. static void usage(void) {
  297.     apr_file_printf(errfile, "Usage:"
  298.     NL);
  299.     apr_file_printf(errfile, "\thtpasswd [-cmdpsD] passwordfile username"
  300.     NL);
  301.     apr_file_printf(errfile, "\thtpasswd -b[cmdpsD] passwordfile username "
  302.                              "password"
  303.     NL
  304.     NL);
  305.     apr_file_printf(errfile, "\thtpasswd -n[mdps] username"
  306.     NL);
  307.     apr_file_printf(errfile, "\thtpasswd -nb[mdps] username password"
  308.     NL);
  309.     apr_file_printf(errfile, " -c  Create a new file."
  310.     NL);
  311.     apr_file_printf(errfile, " -n  Don't update file; display results on "
  312.                              "stdout."
  313.     NL);
  314.     apr_file_printf(errfile, " -m  Force MD5 encryption of the password"
  315.                              " (default)"
  316.                              "."
  317.     NL);
  318.     apr_file_printf(errfile, " -d  Force CRYPT encryption of the password"
  319.                              "."
  320.     NL);
  321.     apr_file_printf(errfile, " -p  Do not encrypt the password (plaintext)."
  322.     NL);
  323.     apr_file_printf(errfile, " -s  Force SHA encryption of the password."
  324.     NL);
  325.     apr_file_printf(errfile, " -b  Use the password from the command line "
  326.                              "rather than prompting for it."
  327.     NL);
  328.     apr_file_printf(errfile, " -D  Delete the specified user."
  329.     NL);
  330.     apr_file_printf(errfile,
  331.                     "On other systems than Windows, NetWare and TPF the '-p' flag will "
  332.                     "probably not work."
  333.     NL);
  334.     apr_file_printf(errfile,
  335.                     "The SHA algorithm does not use a salt and is less secure than "
  336.                     "the MD5 algorithm."
  337.     NL);
  338.     exit(ERR_SYNTAX);
  339. }
  340.  
  341. /*
  342.  * Check to see if the specified file can be opened for the given
  343.  * access.
  344.  */
  345. static int accessible(apr_pool_t *pool, char *fname, int mode) {
  346.     apr_file_t *f = NULL;
  347.  
  348.     if (apr_file_open(&f, fname, mode, APR_OS_DEFAULT, pool) != APR_SUCCESS) {
  349.         return 0;
  350.     }
  351.     apr_file_close(f);
  352.     return 1;
  353. }
  354.  
  355. /*
  356.  * Return true if the named file exists, regardless of permissions.
  357.  */
  358. static int exists(char *fname, apr_pool_t *pool) {
  359.     apr_finfo_t sbuf;
  360.     apr_status_t check;
  361.  
  362.     check = apr_stat(&sbuf, fname, APR_FINFO_TYPE, pool);
  363.     return ((check || sbuf.filetype != APR_REG) ? 0 : 1);
  364. }
  365.  
  366. static void terminate(void) {
  367.     apr_terminate();
  368. #ifdef NETWARE
  369.     pressanykey();
  370. #endif
  371. }
  372.  
  373. static void check_args(apr_pool_t *pool, int argc, const char *const argv[],
  374.                        int *alg, int *mask, char **user, char **pwfilename,
  375.                        char **password) {
  376.     const char *arg;
  377.     int args_left = 2;
  378.     int i;
  379.  
  380.     /*
  381.      * Preliminary check to make sure they provided at least
  382.      * three arguments, we'll do better argument checking as
  383.      * we parse the command line.
  384.      */
  385.     if (argc < 3) {
  386.         usage();
  387.     }
  388.  
  389.     /*
  390.      * Go through the argument list and pick out any options.  They
  391.      * have to precede any other arguments.
  392.      */
  393.     for (i = 1; i < argc; i++) {
  394.         arg = argv[i];
  395.         if (*arg != '-') {
  396.             break;
  397.         }
  398.         while (*++arg != '\0') {
  399.             if (*arg == 'c') {
  400.                 *mask |= APHTP_NEWFILE;
  401.             } else if (*arg == 'n') {
  402.                 *mask |= APHTP_NOFILE;
  403.                 args_left--;
  404.             } else if (*arg == 'm') {
  405.                 *alg = ALG_APMD5;
  406.             } else if (*arg == 's') {
  407.                 *alg = ALG_APSHA;
  408.             } else if (*arg == 'p') {
  409.                 *alg = ALG_PLAIN;
  410.             } else if (*arg == 'd') {
  411.                 *alg = ALG_CRYPT;
  412.             } else if (*arg == 'b') {
  413.                 *mask |= APHTP_NONINTERACTIVE;
  414.                 args_left++;
  415.             } else if (*arg == 'D') {
  416.                 *mask |= APHTP_DELUSER;
  417.             } else {
  418.                 usage();
  419.             }
  420.         }
  421.     }
  422.  
  423.     if ((*mask & APHTP_NEWFILE) && (*mask & APHTP_NOFILE)) {
  424.         apr_file_printf(errfile, "%s: -c and -n options conflict"
  425.         NL, argv[0]);
  426.         exit(ERR_SYNTAX);
  427.     }
  428.     if ((*mask & APHTP_NEWFILE) && (*mask & APHTP_DELUSER)) {
  429.         apr_file_printf(errfile, "%s: -c and -D options conflict"
  430.         NL, argv[0]);
  431.         exit(ERR_SYNTAX);
  432.     }
  433.     if ((*mask & APHTP_NOFILE) && (*mask & APHTP_DELUSER)) {
  434.         apr_file_printf(errfile, "%s: -n and -D options conflict"
  435.         NL, argv[0]);
  436.         exit(ERR_SYNTAX);
  437.     }
  438.     /*
  439.      * Make sure we still have exactly the right number of arguments left
  440.      * (the filename, the username, and possibly the password if -b was
  441.      * specified).
  442.      */
  443.     if ((argc - i) != args_left) {
  444.         usage();
  445.     }
  446.  
  447.     if (*mask & APHTP_NOFILE) {
  448.         i--;
  449.     } else {
  450.         if (strlen(argv[i]) > (APR_PATH_MAX - 1)) {
  451.             apr_file_printf(errfile, "%s: filename too long"
  452.             NL, argv[0]);
  453.             exit(ERR_OVERFLOW);
  454.         }
  455.         *pwfilename = apr_pstrdup(pool, argv[i]);
  456.         if (strlen(argv[i + 1]) > (MAX_STRING_LEN - 1)) {
  457.             apr_file_printf(errfile, "%s: username too long (> %d)"
  458.             NL,
  459.                     argv[0], MAX_STRING_LEN - 1);
  460.             exit(ERR_OVERFLOW);
  461.         }
  462.     }
  463.     *user = apr_pstrdup(pool, argv[i + 1]);
  464.     if ((arg = strchr(*user, ':')) != NULL) {
  465.         apr_file_printf(errfile, "%s: username contains illegal "
  466.                                  "character '%c'"
  467.         NL, argv[0], *arg);
  468.         exit(ERR_BADUSER);
  469.     }
  470.     if (*mask & APHTP_NONINTERACTIVE) {
  471.         if (strlen(argv[i + 2]) > (MAX_STRING_LEN - 1)) {
  472.             apr_file_printf(errfile, "%s: password too long (> %d)"
  473.             NL,
  474.                     argv[0], MAX_STRING_LEN);
  475.             exit(ERR_OVERFLOW);
  476.         }
  477.         *password = apr_pstrdup(pool, argv[i + 2]);
  478.     }
  479. }
  480.  
  481. /*
  482.  * Let's do it.  We end up doing a lot of file opening and closing,
  483.  * but what do we care?  This application isn't run constantly.
  484.  */
  485. int main(int argc, const char *const argv[]) {
  486.     apr_file_t *fpw = NULL;
  487.     char record[MAX_STRING_LEN];
  488.     char line[MAX_STRING_LEN];
  489.     char *password = NULL;
  490.     char *pwfilename = NULL;
  491.     char *user = NULL;
  492.     char tn[] = "htpasswd.tmp.XXXXXX";
  493.     char *dirname;
  494.     char *scratch, cp[MAX_STRING_LEN];
  495.     int found = 0;
  496.     int i;
  497.     int alg = ALG_APMD5;
  498.     int mask = 0;
  499.     apr_pool_t *pool;
  500.     int existing_file = 0;
  501. #if APR_CHARSET_EBCDIC
  502.     apr_status_t rv;
  503.     apr_xlate_t *to_ascii;
  504. #endif
  505.  
  506.     apr_app_initialize(&argc, &argv, NULL);
  507.     atexit(terminate);
  508.     apr_pool_create(&pool, NULL);
  509.     apr_file_open_stderr(&errfile, pool);
  510.  
  511. #if APR_CHARSET_EBCDIC
  512.     rv = apr_xlate_open(&to_ascii, "ISO-8859-1", APR_DEFAULT_CHARSET, pool);
  513.     if (rv) {
  514.         apr_file_printf(errfile, "apr_xlate_open(to ASCII)->%d" NL, rv);
  515.         exit(1);
  516.     }
  517.     rv = apr_SHA1InitEBCDIC(to_ascii);
  518.     if (rv) {
  519.         apr_file_printf(errfile, "apr_SHA1InitEBCDIC()->%d" NL, rv);
  520.         exit(1);
  521.     }
  522.     rv = apr_MD5InitEBCDIC(to_ascii);
  523.     if (rv) {
  524.         apr_file_printf(errfile, "apr_MD5InitEBCDIC()->%d" NL, rv);
  525.         exit(1);
  526.     }
  527. #endif /*APR_CHARSET_EBCDIC*/
  528.  
  529.     check_args(pool, argc, argv, &alg, &mask, &user, &pwfilename, &password);
  530.  
  531.  
  532. #if defined(WIN32) || defined(NETWARE)
  533.     if (alg == ALG_CRYPT) {
  534.         alg = ALG_APMD5;
  535.         apr_file_printf(errfile, "Automatically using MD5 format." NL);
  536.     }
  537. #endif
  538.  
  539. #if (!(defined(WIN32) || defined(TPF) || defined(NETWARE)))
  540.     if (alg == ALG_PLAIN) {
  541.         apr_file_printf(errfile, "Warning: storing passwords as plain text "
  542.                                  "might just not work on this platform."
  543.         NL);
  544.     }
  545. #endif
  546.  
  547.     /*
  548.      * Only do the file checks if we're supposed to frob it.
  549.      */
  550.     if (!(mask & APHTP_NOFILE)) {
  551.         existing_file = exists(pwfilename, pool);
  552.         if (existing_file) {
  553.             /*
  554.              * Check that this existing file is readable and writable.
  555.              */
  556.             if (!accessible(pool, pwfilename, APR_READ | APR_APPEND)) {
  557.                 apr_file_printf(errfile, "%s: cannot open file %s for "
  558.                                          "read/write access"
  559.                 NL, argv[0], pwfilename);
  560.                 exit(ERR_FILEPERM);
  561.             }
  562.         } else {
  563.             /*
  564.              * Error out if -c was omitted for this non-existant file.
  565.              */
  566.             if (!(mask & APHTP_NEWFILE)) {
  567.                 apr_file_printf(errfile,
  568.                                 "%s: cannot modify file %s; use '-c' to create it"
  569.                 NL,
  570.                         argv[0], pwfilename);
  571.                 exit(ERR_FILEPERM);
  572.             }
  573.             /*
  574.              * As it doesn't exist yet, verify that we can create it.
  575.              */
  576.             if (!accessible(pool, pwfilename, APR_CREATE | APR_WRITE)) {
  577.                 apr_file_printf(errfile, "%s: cannot create file %s"
  578.                 NL,
  579.                         argv[0], pwfilename);
  580.                 exit(ERR_FILEPERM);
  581.             }
  582.         }
  583.     }
  584.  
  585.     /*
  586.      * All the file access checks (if any) have been made.  Time to go to work;
  587.      * try to create the record for the username in question.  If that
  588.      * fails, there's no need to waste any time on file manipulations.
  589.      * Any error message text is returned in the record buffer, since
  590.      * the mkrecord() routine doesn't have access to argv[].
  591.      */
  592.     if (!(mask & APHTP_DELUSER)) {
  593.         i = mkrecord(user, record, sizeof(record) - 1,
  594.                      password, alg);
  595.         if (i != 0) {
  596.             apr_file_printf(errfile, "%s: %s"
  597.             NL, argv[0], record);
  598.             exit(i);
  599.         }
  600.         if (mask & APHTP_NOFILE) {
  601.             printf("%s"
  602.             NL, record);
  603.             exit(0);
  604.         }
  605.     }
  606.  
  607.     /*
  608.      * We can access the files the right way, and we have a record
  609.      * to add or update.  Let's do it..
  610.      */
  611.     if (apr_temp_dir_get((const char **) &dirname, pool) != APR_SUCCESS) {
  612.         apr_file_printf(errfile, "%s: could not determine temp dir"
  613.         NL,
  614.                 argv[0]);
  615.         exit(ERR_FILEPERM);
  616.     }
  617.     dirname = apr_psprintf(pool, "%s/%s", dirname, tn);
  618.  
  619.     if (apr_file_mktemp(&ftemp, dirname, 0, pool) != APR_SUCCESS) {
  620.         apr_file_printf(errfile, "%s: unable to create temporary file %s"
  621.         NL,
  622.                 argv[0], dirname);
  623.         exit(ERR_FILEPERM);
  624.     }
  625.  
  626.     /*
  627.      * If we're not creating a new file, copy records from the existing
  628.      * one to the temporary file until we find the specified user.
  629.      */
  630.     if (existing_file && !(mask & APHTP_NEWFILE)) {
  631.         if (apr_file_open(&fpw, pwfilename, APR_READ | APR_BUFFERED,
  632.                           APR_OS_DEFAULT, pool) != APR_SUCCESS) {
  633.             apr_file_printf(errfile, "%s: unable to read file %s"
  634.             NL,
  635.                     argv[0], pwfilename);
  636.             exit(ERR_FILEPERM);
  637.         }
  638.         while (apr_file_gets(line, sizeof(line), fpw) == APR_SUCCESS) {
  639.             char *colon;
  640.  
  641.             strcpy(cp, line);
  642.             scratch = cp;
  643.             while (apr_isspace(*scratch)) {
  644.                 ++scratch;
  645.             }
  646.  
  647.             if (!*scratch || (*scratch == '#')) {
  648.                 putline(ftemp, line);
  649.                 continue;
  650.             }
  651.             /*
  652.              * See if this is our user.
  653.              */
  654.             colon = strchr(scratch, ':');
  655.             if (colon != NULL) {
  656.                 *colon = '\0';
  657.             } else {
  658.                 /*
  659.                  * If we've not got a colon on the line, this could well
  660.                  * not be a valid htpasswd file.
  661.                  * We should bail at this point.
  662.                  */
  663.                 apr_file_printf(errfile, "%s: The file %s does not appear "
  664.                                          "to be a valid htpasswd file."
  665.                 NL,
  666.                         argv[0], pwfilename);
  667.                 apr_file_close(fpw);
  668.                 exit(ERR_INVALID);
  669.             }
  670.             if (strcmp(user, scratch) != 0) {
  671.                 putline(ftemp, line);
  672.                 continue;
  673.             } else {
  674.                 if (!(mask & APHTP_DELUSER)) {
  675.                     /* We found the user we were looking for.
  676.                      * Add him to the file.
  677.                     */
  678.                     apr_file_printf(errfile, "Updating ");
  679.                     putline(ftemp, record);
  680.                     found++;
  681.                 } else {
  682.                     /* We found the user we were looking for.
  683.                      * Delete them from the file.
  684.                      */
  685.                     apr_file_printf(errfile, "Deleting ");
  686.                     found++;
  687.                 }
  688.             }
  689.         }
  690.         apr_file_close(fpw);
  691.     }
  692.     if (!found && !(mask & APHTP_DELUSER)) {
  693.         apr_file_printf(errfile, "Adding ");
  694.         putline(ftemp, record);
  695.     } else if (!found && (mask & APHTP_DELUSER)) {
  696.         apr_file_printf(errfile, "User %s not found"
  697.         NL, user);
  698.         exit(0);
  699.     }
  700.     apr_file_printf(errfile, "password for user %s"
  701.     NL, user);
  702.  
  703.     /* The temporary file has all the data, just copy it to the new location.
  704.      */
  705.     if (apr_file_copy(dirname, pwfilename, APR_FILE_SOURCE_PERMS, pool) !=
  706.         APR_SUCCESS) {
  707.         apr_file_printf(errfile, "%s: unable to update file %s"
  708.         NL,
  709.                 argv[0], pwfilename);
  710.         exit(ERR_FILEPERM);
  711.     }
  712.     apr_file_close(ftemp);
  713.     return 0;
  714. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement