static struct status * status_fromrd(char *path, struct stream *file) { struct status *st; char *id, *line; time_t scantime; int error, ver; /* Get the first line of the file and validate it. */ line = stream_getln(file, NULL); if (line == NULL) { stream_close(file); return (NULL); } id = proto_get_ascii(&line); error = proto_get_int(&line, &ver, 10); if (error) { stream_close(file); return (NULL); } error = proto_get_time(&line, &scantime); if (error || line != NULL) { stream_close(file); return (NULL); } if (strcmp(id, "F") != 0 || ver != STATUS_VERSION) { stream_close(file); return (NULL); } st = status_new(path, scantime, file); st->linenum = 1; return (st); }
static int auth_lookuprecord(char *server, struct srvrecord *auth) { char *home, *line, authfile[FILENAME_MAX]; struct stream *s; int linenum = 0, error; home = getenv("HOME"); if (home == NULL) { lprintf(-1, "Environment variable \"HOME\" is not set\n"); return (STATUS_FAILURE); } snprintf(authfile, sizeof(authfile), "%s/%s", home, AUTHFILE); s = stream_open_file(authfile, O_RDONLY); if (s == NULL) { lprintf(-1, "Could not open file %s\n", authfile); return (STATUS_FAILURE); } while ((line = stream_getln(s, NULL)) != NULL) { linenum++; if (line[0] == '#' || line[0] == '\0') continue; error = auth_parsetoken(&line, auth->server, sizeof(auth->server)); if (error != STATUS_SUCCESS) { lprintf(-1, "%s:%d Missing client name\n", authfile, linenum); goto close; } /* Skip the rest of this line, it isn't what we are looking for. */ if (strcasecmp(auth->server, server) != 0) continue; error = auth_parsetoken(&line, auth->client, sizeof(auth->client)); if (error != STATUS_SUCCESS) { lprintf(-1, "%s:%d Missing password\n", authfile, linenum); goto close; } error = auth_parsetoken(&line, auth->password, sizeof(auth->password)); if (error != STATUS_SUCCESS) { lprintf(-1, "%s:%d Missing comment\n", authfile, linenum); goto close; } stream_close(s); lprintf(2, "Found authentication record for server \"%s\"\n", server); return (STATUS_SUCCESS); } lprintf(-1, "Unknown server \"%s\". Fix your %s\n", server , authfile); memset(auth->password, 0, sizeof(auth->password)); close: stream_close(s); return (STATUS_FAILURE); }
static int auth_domd5auth(struct config *config) { struct stream *s; char *line, *cmd, *challenge, *realm, *client, *srvresponse, *msg; char shrdsecret[MD5_CHARS_MAX], response[MD5_CHARS_MAX]; char clichallenge[MD5_CHARS_MAX]; struct srvrecord auth; int error; lprintf(2, "MD5 authentication started\n"); s = config->server; line = stream_getln(s, NULL); cmd = proto_get_ascii(&line); realm = proto_get_ascii(&line); challenge = proto_get_ascii(&line); if (challenge == NULL || line != NULL || (strcmp(cmd, "AUTHMD5") != 0)) { lprintf(-1, "Invalid server reply to USER\n"); return (STATUS_FAILURE); } client = NULL; response[0] = clichallenge[0] = '.'; response[1] = clichallenge[1] = 0; if (config->reqauth || (strcmp(challenge, ".") != 0)) { if (strcmp(realm, ".") == 0) { lprintf(-1, "Authentication required, but not enabled on server\n"); return (STATUS_FAILURE); } error = auth_lookuprecord(realm, &auth); if (error != STATUS_SUCCESS) return (error); client = auth.client; auth_makesecret(&auth, shrdsecret); } if (strcmp(challenge, ".") != 0) auth_makeresponse(challenge, shrdsecret, response); if (config->reqauth) auth_makechallenge(config, clichallenge); proto_printf(s, "AUTHMD5 %s %s %s\n", client == NULL ? "." : client, response, clichallenge); stream_flush(s); line = stream_getln(s, NULL); cmd = proto_get_ascii(&line); if (cmd == NULL || line == NULL) goto bad; if (strcmp(cmd, "OK") == 0) { srvresponse = proto_get_ascii(&line); if (srvresponse == NULL) goto bad; if (config->reqauth && !auth_checkresponse(srvresponse, clichallenge, shrdsecret)) { lprintf(-1, "Server failed to authenticate itself to client\n"); return (STATUS_FAILURE); } lprintf(2, "MD5 authentication successful\n"); return (STATUS_SUCCESS); } if (strcmp(cmd, "!") == 0) { msg = proto_get_rest(&line); if (msg == NULL) goto bad; lprintf(-1, "Server error: %s\n", msg); return (STATUS_FAILURE); } bad: lprintf(-1, "Invalid server reply to AUTHMD5\n"); return (STATUS_FAILURE); }
static struct statusrec * status_rdraw(struct status *st, char **linep) { struct statusrec sr; char *cmd, *line, *file; if (st->rd == NULL || st->eof) return (NULL); line = stream_getln(st->rd, NULL); if (line == NULL) { if (stream_eof(st->rd)) { if (st->depth != 0) { st->error = STATUS_ERR_TRUNC; return (NULL); } st->eof = 1; return (NULL); } st->error = STATUS_ERR_READ; st->suberror = errno; return (NULL); } st->linenum++; cmd = proto_get_ascii(&line); file = proto_get_ascii(&line); if (file == NULL || strlen(cmd) != 1) { st->error = STATUS_ERR_PARSE; return (NULL); } switch (cmd[0]) { case 'A': sr.sr_type = SR_FILELIVE; break; case 'D': sr.sr_type = SR_DIRDOWN; st->depth++; break; case 'C': sr.sr_type = SR_CHECKOUTLIVE; break; case 'c': sr.sr_type = SR_CHECKOUTDEAD; break; case 'U': sr.sr_type = SR_DIRUP; if (st->depth <= 0) { st->error = STATUS_ERR_BOGUS_DIRUP; return (NULL); } st->depth--; break; case 'V': sr.sr_type = SR_FILELIVE; break; case 'v': sr.sr_type = SR_FILEDEAD; break; default: st->error = STATUS_ERR_BAD_TYPE; st->suberror = cmd[0]; return (NULL); } sr.sr_file = xstrdup(file); if (st->previous != NULL && statusrec_cmp(st->previous, &sr) >= 0) { st->error = STATUS_ERR_UNSORTED; free(sr.sr_file); return (NULL); } if (st->previous == NULL) { st->previous = &st->buf; } else { statusrec_fini(st->previous); statusrec_init(st->previous); } st->previous->sr_type = sr.sr_type; st->previous->sr_file = sr.sr_file; *linep = line; return (st->previous); }