コード例 #1
0
ファイル: auth.c プロジェクト: grayshadow212/usr.src
int auth_login(struct config *config)
{
	struct stream *s;
	char hostbuf[MAXHOSTNAMELEN];
	char *login, *host;
	int error;

	s = config->server;
	error = gethostname(hostbuf, sizeof(hostbuf));
	hostbuf[sizeof(hostbuf) - 1] = '\0';
	if (error)
		host = NULL;
	else
		host = hostbuf;
	login = getlogin();
	proto_printf(s, "USER %s %s\n", login != NULL ? login : "******",
	    host != NULL ? host : "?");
	stream_flush(s);
	error = auth_domd5auth(config);
	return (error);
}
コード例 #2
0
ファイル: auth.c プロジェクト: grayshadow212/usr.src
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);
}
コード例 #3
0
/*
 * Close the status file and free any resource associated with it.
 * It is OK to pass NULL for errmsg only if the status file was
 * opened read-only.  If it wasn't opened read-only, status_close()
 * can produce an error and errmsg is not allowed to be NULL.  If
 * there was no errors, errmsg is set to NULL.
 */
void
status_close(struct status *st, char **errmsg)
{
	struct statusrec *sr;
	char *line, *name;
	int error, type;

	if (st->wr != NULL) {
		if (st->dirty) {
			if (st->current != NULL) {
				error = status_wr(st, st->current);
				if (error) {
					*errmsg = status_errmsg(st);
					goto bad;
				}
				st->current = NULL;
			}
			/* Copy the rest of the file. */
			while ((sr = status_rdraw(st, &line)) != NULL) {
				error = status_wrraw(st, sr, line);
				if (error) {
					*errmsg = status_errmsg(st);
					goto bad;
				}
			}
			if (st->error) {
				*errmsg = status_errmsg(st);
				goto bad;
			}

			/* Close off all the open directories. */
			pathcomp_finish(st->pc);
			while (pathcomp_get(st->pc, &type, &name)) {
				assert(type == PC_DIRUP);
				error = proto_printf(st->wr, "U %s %f\n",
				    name, fattr_bogus);
				if (error) {
					st->error = STATUS_ERR_WRITE;
					st->suberror = errno;
					*errmsg = status_errmsg(st);
					goto bad;
				}
			}

			/* Rename tempfile. */
			error = rename(st->tempfile, st->path);
			if (error) {
				st->error = STATUS_ERR_RENAME;
				st->suberror = errno;
				*errmsg = status_errmsg(st);
				goto bad;
			}
		} else {
			/* Just discard the tempfile. */
			unlink(st->tempfile);
		}
		*errmsg = NULL;
	}
	status_free(st);
	return;
bad:
	status_free(st);
}
コード例 #4
0
/*
 * Open the status file.  If scantime is not -1, the file is opened
 * for updating, otherwise, it is opened read-only. If the status file
 * couldn't be opened, NULL is returned and errmsg is set to the error
 * message.
 */
struct status *
status_open(struct coll *coll, time_t scantime, char **errmsg)
{
	struct status *st;
	struct stream *file;
	struct fattr *fa;
	char *destpath, *path;
	int error, rv;

	path = coll_statuspath(coll);
	file = stream_open_file(path, O_RDONLY);
	if (file == NULL) {
		if (errno != ENOENT) {
			xasprintf(errmsg, "Could not open \"%s\": %s\n",
			    path, strerror(errno));
			free(path);
			return (NULL);
		}
		st = status_fromnull(path);
	} else {
		st = status_fromrd(path, file);
		if (st == NULL) {
			xasprintf(errmsg, "Error in \"%s\": Bad header line",
			    path);
			free(path);
			return (NULL);
		}
	}

	if (scantime != -1) {
		/* Open for writing too. */
		xasprintf(&destpath, "%s/%s/%s/", coll->co_base,
		    coll->co_colldir, coll->co_name);
		st->tempfile = tempname(destpath);
		if (mkdirhier(destpath, coll->co_umask) != 0) {
			xasprintf(errmsg, "Cannot create directories leading "
			    "to \"%s\": %s", destpath, strerror(errno));
			free(destpath);
			status_free(st);
			return (NULL);
		}
		free(destpath);
		st->wr = stream_open_file(st->tempfile,
		    O_CREAT | O_TRUNC | O_WRONLY, 0644);
		if (st->wr == NULL) {
			xasprintf(errmsg, "Cannot create \"%s\": %s",
			    st->tempfile, strerror(errno));
			status_free(st);
			return (NULL);
		}
		fa = fattr_new(FT_FILE, -1);
		fattr_mergedefault(fa);
		fattr_umask(fa, coll->co_umask);
		rv = fattr_install(fa, st->tempfile, NULL);
		fattr_free(fa);
		if (rv == -1) {
			xasprintf(errmsg,
			    "Cannot set attributes for \"%s\": %s",
			    st->tempfile, strerror(errno));
			status_free(st);
			return (NULL);
		}
		if (scantime != st->scantime)
			st->dirty = 1;
		error = proto_printf(st->wr, "F %d %t\n", STATUS_VERSION,
		    scantime);
		if (error) {
			st->error = STATUS_ERR_WRITE;
			st->suberror = errno;
			*errmsg = status_errmsg(st);
			status_free(st);
			return (NULL);
		}
	}
	return (st);
}
コード例 #5
0
static int
status_wrraw(struct status *st, struct statusrec *sr, char *line)
{
	char *name;
	char cmd;
	int error, ret, type;

	if (st->wr == NULL)
		return (0);

	/*
	 * Keep the compressor in sync.  At this point, the necessary
	 * DirDowns and DirUps should have already been emitted, so the
	 * compressor should return exactly one value in the PC_DIRDOWN
	 * and PC_DIRUP case and none in the PC_FILE case.
	 */
	if (sr->sr_type == SR_DIRDOWN)
		pathcomp_put(st->pc, PC_DIRDOWN, sr->sr_file);
	else if (sr->sr_type == SR_DIRUP)
		pathcomp_put(st->pc, PC_DIRUP, sr->sr_file);
	else
		pathcomp_put(st->pc, PC_FILE, sr->sr_file);
	if (sr->sr_type == SR_DIRDOWN || sr->sr_type == SR_DIRUP) {
		ret = pathcomp_get(st->pc, &type, &name);
		assert(ret);
		if (sr->sr_type == SR_DIRDOWN)
			assert(type == PC_DIRDOWN);
		else
			assert(type == PC_DIRUP);
	}
	ret = pathcomp_get(st->pc, &type, &name);
	assert(!ret);

	switch (sr->sr_type) {
	case SR_DIRDOWN:
		cmd = 'D';
		break;
	case SR_DIRUP:
		cmd = 'U';
		break;
	case SR_CHECKOUTLIVE:
		cmd = 'C';
		break;
	case SR_CHECKOUTDEAD:
		cmd = 'c';
		break;
	case SR_FILELIVE:
		cmd = 'V';
		break;
	case SR_FILEDEAD:
		cmd = 'v';
		break;
	default:
		assert(0);
		return (-1);
	}
	if (sr->sr_type == SR_DIRDOWN)
		error = proto_printf(st->wr, "%c %S\n", cmd, sr->sr_file);
	else
		error = proto_printf(st->wr, "%c %s %S\n", cmd, sr->sr_file,
		    line);
	if (error) {
		st->error = STATUS_ERR_WRITE;
		st->suberror = errno;
		return (-1);
	}
	return (0);
}
コード例 #6
0
static int
status_wr(struct status *st, struct statusrec *sr)
{
	struct pathcomp *pc;
	const struct fattr *fa;
	char *name;
	int error, type, usedirupattr;

	pc = st->pc;
	error = 0;
	usedirupattr = 0;
	if (sr->sr_type == SR_DIRDOWN) {
		pathcomp_put(pc, PC_DIRDOWN, sr->sr_file);
	} else if (sr->sr_type == SR_DIRUP) {
		pathcomp_put(pc, PC_DIRUP, sr->sr_file);
		usedirupattr = 1;
	} else {
		pathcomp_put(pc, PC_FILE, sr->sr_file);
	}

	while (pathcomp_get(pc, &type, &name)) {
		if (type == PC_DIRDOWN) {
			error = proto_printf(st->wr, "D %s\n", name);
		} else if (type == PC_DIRUP) {
			if (usedirupattr)
				fa = sr->sr_clientattr;
			else
				fa = fattr_bogus;
			usedirupattr = 0;
			error = proto_printf(st->wr, "U %s %f\n", name, fa);
		}
		if (error)
			goto bad;
	}

	switch (sr->sr_type) {
	case SR_DIRDOWN:
	case SR_DIRUP:
		/* Already emitted above. */
		break;
	case SR_CHECKOUTLIVE:
		error = proto_printf(st->wr, "C %s %s %s %f %s %s %f\n",
		    sr->sr_file, sr->sr_tag, sr->sr_date, sr->sr_serverattr,
		    sr->sr_revnum, sr->sr_revdate, sr->sr_clientattr);
		break;
	case SR_CHECKOUTDEAD:
		error = proto_printf(st->wr, "c %s %s %s %f\n", sr->sr_file,
		    sr->sr_tag, sr->sr_date, sr->sr_serverattr);
		break;
	case SR_FILELIVE:
		error = proto_printf(st->wr, "V %s %f\n", sr->sr_file,
		    sr->sr_clientattr);
		break;
	case SR_FILEDEAD:
		error = proto_printf(st->wr, "v %s %f\n", sr->sr_file,
		    sr->sr_clientattr);
		break;
	}
	if (error)
		goto bad;
	return (0);
bad:
	st->error = STATUS_ERR_WRITE;
	st->suberror = errno;
	return (-1);
}