Diff for /embedaddon/rsync/authenticate.c between versions 1.1.1.2 and 1.1.1.4

version 1.1.1.2, 2013/10/14 07:51:14 version 1.1.1.4, 2021/03/17 00:32:36
Line 2 Line 2
  * Support rsync daemon authentication.   * Support rsync daemon authentication.
  *   *
  * Copyright (C) 1998-2000 Andrew Tridgell   * Copyright (C) 1998-2000 Andrew Tridgell
 * Copyright (C) 2002-2013 Wayne Davison * Copyright (C) 2002-2020 Wayne Davison
  *   *
  * This program is free software; you can redistribute it and/or modify   * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by   * it under the terms of the GNU General Public License as published by
Line 20 Line 20
   
 #include "rsync.h"  #include "rsync.h"
 #include "itypes.h"  #include "itypes.h"
   #include "ifuncs.h"
   
 extern int read_only;  extern int read_only;
 extern char *password_file;  extern char *password_file;
Line 71  static void gen_challenge(const char *addr, char *chal Line 72  static void gen_challenge(const char *addr, char *chal
         SIVAL(input, 20, tv.tv_usec);          SIVAL(input, 20, tv.tv_usec);
         SIVAL(input, 24, getpid());          SIVAL(input, 24, getpid());
   
        sum_init(0);        sum_init(-1, 0);
         sum_update(input, sizeof input);          sum_update(input, sizeof input);
         len = sum_end(digest);          len = sum_end(digest);
   
Line 85  static void generate_hash(const char *in, const char * Line 86  static void generate_hash(const char *in, const char *
         char buf[MAX_DIGEST_LEN];          char buf[MAX_DIGEST_LEN];
         int len;          int len;
   
        sum_init(0);        sum_init(-1, 0);
         sum_update(in, strlen(in));          sum_update(in, strlen(in));
         sum_update(challenge, strlen(challenge));          sum_update(challenge, strlen(challenge));
         len = sum_end(buf);          len = sum_end(buf);
Line 102  static const char *check_secret(int module, const char Line 103  static const char *check_secret(int module, const char
         char pass2[MAX_DIGEST_LEN*2];          char pass2[MAX_DIGEST_LEN*2];
         const char *fname = lp_secrets_file(module);          const char *fname = lp_secrets_file(module);
         STRUCT_STAT st;          STRUCT_STAT st;
        int fd, ok = 1;        int ok = 1;
         int user_len = strlen(user);          int user_len = strlen(user);
         int group_len = group ? strlen(group) : 0;          int group_len = group ? strlen(group) : 0;
         char *err;          char *err;
           FILE *fh;
   
        if (!fname || !*fname || (fd = open(fname, O_RDONLY)) < 0)        if (!fname || !*fname || (fh = fopen(fname, "r")) == NULL)
                 return "no secrets file";                  return "no secrets file";
   
        if (do_fstat(fd, &st) == -1) {        if (do_fstat(fileno(fh), &st) == -1) {
                 rsyserr(FLOG, errno, "fstat(%s)", fname);                  rsyserr(FLOG, errno, "fstat(%s)", fname);
                 ok = 0;                  ok = 0;
         } else if (lp_strict_modes(module)) {          } else if (lp_strict_modes(module)) {
                 if ((st.st_mode & 06) != 0) {                  if ((st.st_mode & 06) != 0) {
                         rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");                          rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
                         ok = 0;                          ok = 0;
                } else if (MY_UID() == 0 && st.st_uid != 0) {                } else if (MY_UID() == ROOT_UID && st.st_uid != ROOT_UID) {
                         rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n");                          rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n");
                         ok = 0;                          ok = 0;
                 }                  }
         }          }
         if (!ok) {          if (!ok) {
                close(fd);                fclose(fh);
                 return "ignoring secrets file";                  return "ignoring secrets file";
         }          }
   
         if (*user == '#') {          if (*user == '#') {
                 /* Reject attempt to match a comment. */                  /* Reject attempt to match a comment. */
                close(fd);                fclose(fh);
                 return "invalid username";                  return "invalid username";
         }          }
   
         /* Try to find a line that starts with the user (or @group) name and a ':'. */          /* Try to find a line that starts with the user (or @group) name and a ':'. */
         err = "secret not found";          err = "secret not found";
        while ((user || group) && read_line_old(fd, line, sizeof line, 1)) {        while ((user || group) && fgets(line, sizeof line, fh) != NULL) {
                const char **ptr, *s;                const char **ptr, *s = strtok(line, "\n\r");
                 int len;                  int len;
                if (*line == '@') {                if (!s)
                         continue;
                 if (*s == '@') {
                         ptr = &group;                          ptr = &group;
                         len = group_len;                          len = group_len;
                        s = line+1;                        s++;
                 } else {                  } else {
                         ptr = &user;                          ptr = &user;
                         len = user_len;                          len = user_len;
                         s = line;  
                 }                  }
                 if (!*ptr || strncmp(s, *ptr, len) != 0 || s[len] != ':')                  if (!*ptr || strncmp(s, *ptr, len) != 0 || s[len] != ':')
                         continue;                          continue;
Line 158  static const char *check_secret(int module, const char Line 161  static const char *check_secret(int module, const char
                 *ptr = NULL; /* Don't look for name again. */                  *ptr = NULL; /* Don't look for name again. */
         }          }
   
        close(fd);        fclose(fh);
   
        memset(line, 0, sizeof line);        force_memzero(line, sizeof line);
        memset(pass2, 0, sizeof pass2);        force_memzero(pass2, sizeof pass2);
   
         return err;          return err;
 }  }
Line 193  static const char *getpassf(const char *filename) Line 196  static const char *getpassf(const char *filename)
                         rprintf(FERROR, "ERROR: password file must not be other-accessible\n");                          rprintf(FERROR, "ERROR: password file must not be other-accessible\n");
                         exit_cleanup(RERR_SYNTAX);                          exit_cleanup(RERR_SYNTAX);
                 }                  }
                if (MY_UID() == 0 && st.st_uid != 0) {                if (MY_UID() == ROOT_UID && st.st_uid != ROOT_UID) {
                         rprintf(FERROR, "ERROR: password file must be owned by root when running as root\n");                          rprintf(FERROR, "ERROR: password file must be owned by root when running as root\n");
                         exit_cleanup(RERR_SYNTAX);                          exit_cleanup(RERR_SYNTAX);
                 }                  }
Line 224  char *auth_server(int f_in, int f_out, int module, con Line 227  char *auth_server(int f_in, int f_out, int module, con
         char *users = lp_auth_users(module);          char *users = lp_auth_users(module);
         char challenge[MAX_DIGEST_LEN*2];          char challenge[MAX_DIGEST_LEN*2];
         char line[BIGPATHBUFLEN];          char line[BIGPATHBUFLEN];
        char **auth_uid_groups = NULL;        const char **auth_uid_groups = NULL;
         int auth_uid_groups_cnt = -1;          int auth_uid_groups_cnt = -1;
         const char *err = NULL;          const char *err = NULL;
         int group_match = -1;          int group_match = -1;
Line 248  char *auth_server(int f_in, int f_out, int module, con Line 251  char *auth_server(int f_in, int f_out, int module, con
         }          }
         *pass++ = '\0';          *pass++ = '\0';
   
        if (!(users = strdup(users)))        users = strdup(users);
                out_of_memory("auth_server"); 
   
         for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {          for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
                 char *opts;                  char *opts;
Line 277  char *auth_server(int f_in, int f_out, int module, con Line 279  char *auth_server(int f_in, int f_out, int module, con
                         /* See if authorizing user is a real user, and if so, see                          /* See if authorizing user is a real user, and if so, see
                          * if it is in a group that matches tok+1 wildmat. */                           * if it is in a group that matches tok+1 wildmat. */
                         if (auth_uid_groups_cnt < 0) {                          if (auth_uid_groups_cnt < 0) {
                                gid_t gid_list[64];                                item_list gid_list = EMPTY_ITEM_LIST;
                                 uid_t auth_uid;                                  uid_t auth_uid;
                                 auth_uid_groups_cnt = sizeof gid_list / sizeof (gid_t);  
                                 if (!user_to_uid(line, &auth_uid, False)                                  if (!user_to_uid(line, &auth_uid, False)
                                 || getallgroups(auth_uid, gid_list, &auth_uid_groups_cnt) != NULL)                                 || getallgroups(auth_uid, &gid_list) != NULL)
                                         auth_uid_groups_cnt = 0;                                          auth_uid_groups_cnt = 0;
                                 else {                                  else {
                                        if ((auth_uid_groups = new_array(char *, auth_uid_groups_cnt)) == NULL)                                        gid_t *gid_array = gid_list.items;
                                                out_of_memory("auth_server");                                        auth_uid_groups_cnt = gid_list.count;
                                         auth_uid_groups = new_array(const char *, auth_uid_groups_cnt);
                                         for (j = 0; j < auth_uid_groups_cnt; j++)                                          for (j = 0; j < auth_uid_groups_cnt; j++)
                                                auth_uid_groups[j] = gid_to_group(gid_list[j]);                                                auth_uid_groups[j] = gid_to_group(gid_array[j]);
                                 }                                  }
                         }                          }
                         for (j = 0; j < auth_uid_groups_cnt; j++) {                          for (j = 0; j < auth_uid_groups_cnt; j++) {
Line 311  char *auth_server(int f_in, int f_out, int module, con Line 313  char *auth_server(int f_in, int f_out, int module, con
         else if (opt_ch == 'd')          else if (opt_ch == 'd')
                 err = "denied by rule";                  err = "denied by rule";
         else {          else {
                char *group = group_match >= 0 ? auth_uid_groups[group_match] : NULL;                const char *group = group_match >= 0 ? auth_uid_groups[group_match] : NULL;
                 err = check_secret(module, line, group, challenge, pass);                  err = check_secret(module, line, group, challenge, pass);
         }          }
   
        memset(challenge, 0, sizeof challenge);        force_memzero(challenge, sizeof challenge);
        memset(pass, 0, strlen(pass));        force_memzero(pass, strlen(pass));
   
         if (auth_uid_groups) {          if (auth_uid_groups) {
                 int j;                  int j;
                 for (j = 0; j < auth_uid_groups_cnt; j++) {                  for (j = 0; j < auth_uid_groups_cnt; j++) {
                         if (auth_uid_groups[j])                          if (auth_uid_groups[j])
                                free(auth_uid_groups[j]);                                free((char*)auth_uid_groups[j]);
                 }                  }
                 free(auth_uid_groups);                  free(auth_uid_groups);
         }          }
Line 354  void auth_client(int fd, const char *user, const char  Line 356  void auth_client(int fd, const char *user, const char 
                 /* XXX: cyeoh says that getpass is deprecated, because                  /* XXX: cyeoh says that getpass is deprecated, because
                  * it may return a truncated password on some systems,                   * it may return a truncated password on some systems,
                  * and it is not in the LSB.                   * and it is not in the LSB.
                 *                 *
                 * Andrew Klein says that getpassphrase() is present                 * Andrew Klein says that getpassphrase() is present
                 * on Solaris and reads up to 256 characters.                 * on Solaris and reads up to 256 characters.
                 *                 *
                 * OpenBSD has a readpassphrase() that might be more suitable.                 * OpenBSD has a readpassphrase() that might be more suitable.
                 */                 */
                 pass = getpass("Password: ");                  pass = getpass("Password: ");
         }          }
   

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>