Return the secret for a user from the secret file, null terminated. * Maximum length is len (not counting the null). */
| 98 | /* Return the secret for a user from the secret file, null terminated. |
| 99 | * Maximum length is len (not counting the null). */ |
| 100 | static const char *check_secret(int module, const char *user, const char *group, |
| 101 | const char *challenge, const char *pass) |
| 102 | { |
| 103 | char line[1024]; |
| 104 | char pass2[MAX_DIGEST_LEN*2]; |
| 105 | const char *fname = lp_secrets_file(module); |
| 106 | STRUCT_STAT st; |
| 107 | int ok = 1; |
| 108 | int user_len = strlen(user); |
| 109 | int group_len = group ? strlen(group) : 0; |
| 110 | char *err; |
| 111 | FILE *fh; |
| 112 | |
| 113 | if (!fname || !*fname || (fh = fopen(fname, "r")) == NULL) |
| 114 | return "no secrets file"; |
| 115 | |
| 116 | if (do_fstat(fileno(fh), &st) == -1) { |
| 117 | rsyserr(FLOG, errno, "fstat(%s)", fname); |
| 118 | ok = 0; |
| 119 | } else if (lp_strict_modes(module)) { |
| 120 | if ((st.st_mode & 06) != 0) { |
| 121 | rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n"); |
| 122 | ok = 0; |
| 123 | } else if (MY_UID() == ROOT_UID && st.st_uid != ROOT_UID) { |
| 124 | rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n"); |
| 125 | ok = 0; |
| 126 | } |
| 127 | } |
| 128 | if (!ok) { |
| 129 | fclose(fh); |
| 130 | return "ignoring secrets file"; |
| 131 | } |
| 132 | |
| 133 | if (*user == '#') { |
| 134 | /* Reject attempt to match a comment. */ |
| 135 | fclose(fh); |
| 136 | return "invalid username"; |
| 137 | } |
| 138 | |
| 139 | /* Try to find a line that starts with the user (or @group) name and a ':'. */ |
| 140 | err = "secret not found"; |
| 141 | while ((user || group) && fgets(line, sizeof line, fh) != NULL) { |
| 142 | const char **ptr, *s = strtok(line, "\n\r"); |
| 143 | int len; |
| 144 | if (!s) |
| 145 | continue; |
| 146 | if (*s == '@') { |
| 147 | ptr = &group; |
| 148 | len = group_len; |
| 149 | s++; |
| 150 | } else { |
| 151 | ptr = &user; |
| 152 | len = user_len; |
| 153 | } |
| 154 | if (!*ptr || strncmp(s, *ptr, len) != 0 || s[len] != ':') |
| 155 | continue; |
| 156 | generate_hash(s+len+1, challenge, pass2); |
| 157 | if (strcmp(pass, pass2) == 0) { |
no test coverage detected