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_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 int statusrec_cook(struct statusrec *sr, char *line) { char *clientattr, *serverattr; switch (sr->sr_type) { case SR_FILEDEAD: case SR_FILELIVE: clientattr = proto_get_ascii(&line); if (clientattr == NULL || line != NULL) return (-1); sr->sr_clientattr = fattr_decode(clientattr); if (sr->sr_clientattr == NULL) return (-1); break; case SR_DIRDOWN: /* Nothing to do. */ if (line != NULL) return (-1); break; case SR_CHECKOUTLIVE: sr->sr_tag = proto_get_ascii(&line); sr->sr_date = proto_get_ascii(&line); serverattr = proto_get_ascii(&line); sr->sr_revnum = proto_get_ascii(&line); sr->sr_revdate = proto_get_ascii(&line); clientattr = proto_get_ascii(&line); if (clientattr == NULL || line != NULL) return (-1); sr->sr_serverattr = fattr_decode(serverattr); if (sr->sr_serverattr == NULL) return (-1); sr->sr_clientattr = fattr_decode(clientattr); if (sr->sr_clientattr == NULL) { fattr_free(sr->sr_serverattr); return (-1); } break; case SR_CHECKOUTDEAD: sr->sr_tag = proto_get_ascii(&line); sr->sr_date = proto_get_ascii(&line); serverattr = proto_get_ascii(&line); if (serverattr == NULL || line != NULL) return (-1); sr->sr_serverattr = fattr_decode(serverattr); if (sr->sr_serverattr == NULL) return (-1); break; case SR_DIRUP: clientattr = proto_get_ascii(&line); if (clientattr == NULL || line != NULL) return (-1); sr->sr_clientattr = fattr_decode(clientattr); if (sr->sr_clientattr == NULL) return (-1); break; default: return (-1); } return (0); }
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); }