00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "rsync.h"
00022
00023
00024
00025
00026
00027 static void base64_encode(char *buf, int len, char *out)
00028 {
00029 char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00030 int bit_offset, byte_offset, idx, i;
00031 unsigned char *d = (unsigned char *)buf;
00032 int bytes = (len*8 + 5)/6;
00033
00034 memset(out, 0, bytes+1);
00035
00036 for (i=0;i<bytes;i++) {
00037 byte_offset = (i*6)/8;
00038 bit_offset = (i*6)%8;
00039 if (bit_offset < 3) {
00040 idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
00041 } else {
00042 idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
00043 if (byte_offset+1 < len) {
00044 idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
00045 }
00046 }
00047 out[i] = b64[idx];
00048 }
00049 }
00050
00051
00052 static void gen_challenge(char *addr, char *challenge)
00053 {
00054 char input[32];
00055 struct timeval tv;
00056
00057 memset(input, 0, sizeof(input));
00058
00059 strlcpy((char *)input, addr, 17);
00060 sys_gettimeofday(&tv);
00061 SIVAL(input, 16, tv.tv_sec);
00062 SIVAL(input, 20, tv.tv_usec);
00063 SIVAL(input, 24, getpid());
00064
00065 sum_init();
00066 sum_update(input, sizeof(input));
00067 sum_end(challenge);
00068 }
00069
00070
00071
00072
00073 static int get_secret(int module, char *user, char *secret, int len)
00074 {
00075 char *fname = lp_secrets_file(module);
00076 int fd, found=0;
00077 char line[MAXPATHLEN];
00078 char *p, *pass=NULL;
00079 STRUCT_STAT st;
00080 int ok = 1;
00081 extern int am_root;
00082
00083 if (!fname || !*fname) return 0;
00084
00085 fd = open(fname,O_RDONLY);
00086 if (fd == -1) return 0;
00087
00088 if (do_stat(fname, &st) == -1) {
00089 rsyserr(FERROR, errno, "stat(%s)", fname);
00090 ok = 0;
00091 } else if (lp_strict_modes(module)) {
00092 if ((st.st_mode & 06) != 0) {
00093 rprintf(FERROR,"secrets file must not be other-accessible (see strict modes option)\n");
00094 ok = 0;
00095 } else if (am_root && (st.st_uid != 0)) {
00096 rprintf(FERROR,"secrets file must be owned by root when running as root (see strict modes)\n");
00097 ok = 0;
00098 }
00099 }
00100 if (!ok) {
00101 rprintf(FERROR,"continuing without secrets file\n");
00102 close(fd);
00103 return 0;
00104 }
00105
00106 while (!found) {
00107 int i = 0;
00108 memset(line, 0, sizeof line);
00109 while ((size_t) i < (sizeof(line)-1)) {
00110 if (read(fd, &line[i], 1) != 1) {
00111 memset(line, 0, sizeof(line));
00112 close(fd);
00113 return 0;
00114 }
00115 if (line[i] == '\r') continue;
00116 if (line[i] == '\n') break;
00117 i++;
00118 }
00119 line[i] = 0;
00120 if (line[0] == '#') continue;
00121 p = strchr(line,':');
00122 if (!p) continue;
00123 *p = 0;
00124 if (strcmp(user, line)) continue;
00125 pass = p+1;
00126 found = 1;
00127 }
00128
00129 close(fd);
00130 if (!found) return 0;
00131
00132 strlcpy(secret, pass, len);
00133 return 1;
00134 }
00135
00136 static char *getpassf(char *filename)
00137 {
00138 char buffer[100];
00139 int fd=0;
00140 STRUCT_STAT st;
00141 int ok = 1;
00142 extern int am_root;
00143 char *envpw=getenv("RSYNC_PASSWORD");
00144
00145 if (!filename) return NULL;
00146
00147 if ( (fd=open(filename,O_RDONLY)) == -1) {
00148 rsyserr(FERROR, errno, "could not open password file \"%s\"",filename);
00149 if (envpw) rprintf(FERROR,"falling back to RSYNC_PASSWORD environment variable.\n");
00150 return NULL;
00151 }
00152
00153 if (do_stat(filename, &st) == -1) {
00154 rsyserr(FERROR, errno, "stat(%s)", filename);
00155 ok = 0;
00156 } else if ((st.st_mode & 06) != 0) {
00157 rprintf(FERROR,"password file must not be other-accessible\n");
00158 ok = 0;
00159 } else if (am_root && (st.st_uid != 0)) {
00160 rprintf(FERROR,"password file must be owned by root when running as root\n");
00161 ok = 0;
00162 }
00163 if (!ok) {
00164 rprintf(FERROR,"continuing without password file\n");
00165 if (envpw) rprintf(FERROR,"using RSYNC_PASSWORD environment variable.\n");
00166 close(fd);
00167 return NULL;
00168 }
00169
00170 if (envpw) rprintf(FERROR,"RSYNC_PASSWORD environment variable ignored\n");
00171
00172 buffer[sizeof(buffer)-1]='\0';
00173 if (read(fd,buffer,sizeof(buffer)-1) > 0)
00174 {
00175 char *p = strtok(buffer,"\n\r");
00176 close(fd);
00177 if (p) p = strdup(p);
00178 return p;
00179 }
00180
00181 return NULL;
00182 }
00183
00184
00185 static void generate_hash(char *in, char *challenge, char *out)
00186 {
00187 char buf[16];
00188
00189 sum_init();
00190 sum_update(in, strlen(in));
00191 sum_update(challenge, strlen(challenge));
00192 sum_end(buf);
00193
00194 base64_encode(buf, 16, out);
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 char *auth_server(int fd, int module, char *addr, char *leader)
00207 {
00208 char *users = lp_auth_users(module);
00209 char challenge[16];
00210 char b64_challenge[30];
00211 char line[MAXPATHLEN];
00212 static char user[100];
00213 char secret[100];
00214 char pass[30];
00215 char pass2[30];
00216 char *tok;
00217
00218
00219 if (!users || !*users) return "";
00220
00221 gen_challenge(addr, challenge);
00222
00223 base64_encode(challenge, 16, b64_challenge);
00224
00225 io_printf(fd,"%s%s\n", leader, b64_challenge);
00226
00227 if (!read_line(fd, line, sizeof(line)-1)) {
00228 return NULL;
00229 }
00230
00231 memset(user, 0, sizeof(user));
00232 memset(pass, 0, sizeof(pass));
00233
00234 if (sscanf(line,"%99s %29s", user, pass) != 2) {
00235 return NULL;
00236 }
00237
00238 users = strdup(users);
00239 if (!users) return NULL;
00240
00241 for (tok=strtok(users," ,\t"); tok; tok = strtok(NULL," ,\t")) {
00242 if (fnmatch(tok, user, 0) == 0) break;
00243 }
00244 free(users);
00245
00246 if (!tok) {
00247 return NULL;
00248 }
00249
00250 memset(secret, 0, sizeof(secret));
00251 if (!get_secret(module, user, secret, sizeof(secret)-1)) {
00252 memset(secret, 0, sizeof(secret));
00253 return NULL;
00254 }
00255
00256 generate_hash(secret, b64_challenge, pass2);
00257 memset(secret, 0, sizeof(secret));
00258
00259 if (strcmp(pass, pass2) == 0)
00260 return user;
00261
00262 return NULL;
00263 }
00264
00265
00266 void auth_client(int fd, char *user, char *challenge)
00267 {
00268 char *pass;
00269 char pass2[30];
00270 extern char *password_file;
00271
00272 if (!user || !*user) return;
00273
00274 if (!(pass=getpassf(password_file)) && !(pass=getenv("RSYNC_PASSWORD"))) {
00275
00276
00277
00278 pass = getpass("Password: ");
00279 }
00280
00281 if (!pass || !*pass) {
00282 pass = "";
00283 }
00284
00285 generate_hash(pass, challenge, pass2);
00286 io_printf(fd, "%s %s\n", user, pass2);
00287 }
00288
00289