static void
process_realpath(u_int32_t id)
{
	char resolvedname[MAXPATHLEN];
	char *path;

	path = get_string(NULL);
	if (path[0] == '\0') {
		free(path);
		path = xstrdup(".");
	}
	debug3("request %u: realpath", id);
	verbose("realpath \"%s\"", path);
	if (realpath(path, resolvedname) == NULL) {
		send_status(id, errno_to_portable(errno));
	} else {
		Stat s;
		attrib_clear(&s.attrib);
		s.name = s.long_name = resolvedname;
		send_names(id, 1, &s);
	}

#ifdef NERSC_MOD
 	char* t1buf = encode_string(path, strlen(path));
 	s_audit("sftp_process_realpath_3", "count=%i int=%d uristring=%s",
 		get_client_session_id(), (int)getppid(), t1buf);
 	free(t1buf);
#endif

	free(path);
}
static void
process_fstat(u_int32_t id)
{
	Attrib a;
	struct stat st;
	int fd, ret, handle, status = SSH2_FX_FAILURE;

	handle = get_handle();
	debug("request %u: fstat \"%s\" (handle %u)",
	    id, handle_to_name(handle), handle);
	fd = handle_to_fd(handle);
	if (fd >= 0) {
		ret = fstat(fd, &st);
		if (ret < 0) {
			status = errno_to_portable(errno);
		} else {
			stat_to_attrib(&st, &a);
			send_attrib(id, &a);
			status = SSH2_FX_OK;
		}
	}
	if (status != SSH2_FX_OK)
		send_status(id, status);

#ifdef NERSC_MOD
	s_audit("sftp_process_fstat_3", "count=%i int=%d int=%d", 
		get_client_session_id(), (int)getppid(), handle);
#endif
}
static void
process_readlink(u_int32_t id)
{
	int len;
	char buf[MAXPATHLEN];
	char *path;

	path = get_string(NULL);
	debug3("request %u: readlink", id);
	verbose("readlink \"%s\"", path);
	if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
		send_status(id, errno_to_portable(errno));
	else {
		Stat s;

		buf[len] = '\0';
		attrib_clear(&s.attrib);
		s.name = s.long_name = buf;
		send_names(id, 1, &s);
	}

#ifdef NERSC_MOD
        char* t1buf = encode_string( path, strlen(path));
        s_audit("sftp_process_readlink_3", "count=%i int=%d uristring=%s",
                get_client_session_id(), (int)getppid(), t1buf);
        free(t1buf);
#endif

	free(path);
}
static void
send_statvfs(u_int32_t id, struct statvfs *st)
{
	Buffer msg;
	u_int64_t flag;

	flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0;
	flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0;

	buffer_init(&msg);
	buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY);
	buffer_put_int(&msg, id);
	buffer_put_int64(&msg, st->f_bsize);
	buffer_put_int64(&msg, st->f_frsize);
	buffer_put_int64(&msg, st->f_blocks);
	buffer_put_int64(&msg, st->f_bfree);
	buffer_put_int64(&msg, st->f_bavail);
	buffer_put_int64(&msg, st->f_files);
	buffer_put_int64(&msg, st->f_ffree);
	buffer_put_int64(&msg, st->f_favail);
	buffer_put_int64(&msg, FSID_TO_ULONG(st->f_fsid));
	buffer_put_int64(&msg, flag);
	buffer_put_int64(&msg, st->f_namemax);
	send_msg(&msg);
	buffer_free(&msg);

#ifdef NERSC_MOD
	s_audit("sftp_process_init_3", "count=%i int=%d int=%d", 
		get_client_session_id(), (int)getppid(), version);
#endif
}
static void
process_mkdir(u_int32_t id)
{
	Attrib *a;
	char *name;
	int ret, mode, status = SSH2_FX_FAILURE;

	name = get_string(NULL);
	a = get_attrib();
	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
	    a->perm & 07777 : 0777;
	debug3("request %u: mkdir", id);
	logit("mkdir name \"%s\" mode 0%o", name, mode);
	ret = mkdir(name, mode);
	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
	send_status(id, status);

#ifdef NERSC_MOD
 	char* t1buf = encode_string(name, strlen(name));
 	s_audit("sftp_process_mkdir_3", "count=%i int=%d uristring=%s",
 		get_client_session_id(), (int)getpid(), t1buf);
 	free(t1buf);
#endif

	free(name);
}
static void
process_readdir(u_int32_t id)
{
	DIR *dirp;
	struct dirent *dp;
	char *path;
	int handle;

	handle = get_handle();
	debug("request %u: readdir \"%s\" (handle %d)", id,
	    handle_to_name(handle), handle);
	dirp = handle_to_dir(handle);
	path = handle_to_name(handle);
	if (dirp == NULL || path == NULL) {
		send_status(id, SSH2_FX_FAILURE);
	} else {
		struct stat st;
		char pathname[MAXPATHLEN];
		Stat *stats;
		int nstats = 10, count = 0, i;

		stats = xcalloc(nstats, sizeof(Stat));
		while ((dp = readdir(dirp)) != NULL) {
			if (count >= nstats) {
				nstats *= 2;
				stats = xrealloc(stats, nstats, sizeof(Stat));
			}
/* XXX OVERFLOW ? */
			snprintf(pathname, sizeof pathname, "%s%s%s", path,
			    strcmp(path, "/") ? "/" : "", dp->d_name);
			if (lstat(pathname, &st) < 0)
				continue;
			stat_to_attrib(&st, &(stats[count].attrib));
			stats[count].name = xstrdup(dp->d_name);
			stats[count].long_name = ls_file(dp->d_name, &st, 0, 0);
			count++;
			/* send up to 100 entries in one message */
			/* XXX check packet size instead */
			if (count == 100)
				break;
		}
		if (count > 0) {
			send_names(id, count, stats);
			for (i = 0; i < count; i++) {
				free(stats[i].name);
				free(stats[i].long_name);
			}
		} else {
			send_status(id, SSH2_FX_EOF);
		}

#ifdef NERSC_MOD
 	char* t1buf = encode_string(path, strlen(path));
 	s_audit("sftp_process_readdir_3", "count=%i int=%d uristring=%s",
 		get_client_session_id(), (int)getppid(), t1buf);
#endif

		free(stats);
	}
}
static void
process_opendir(u_int32_t id)
{
	DIR *dirp = NULL;
	char *path;
	int handle, status = SSH2_FX_FAILURE;

	path = get_string(NULL);
	debug3("request %u: opendir", id);
	logit("opendir \"%s\"", path);
	dirp = opendir(path);
	if (dirp == NULL) {
		status = errno_to_portable(errno);
	} else {
		handle = handle_new(HANDLE_DIR, path, 0, 0, dirp);
		if (handle < 0) {
			closedir(dirp);
		} else {
			send_handle(id, handle);
			status = SSH2_FX_OK;
		}

	}
	if (status != SSH2_FX_OK)
		send_status(id, status);

#ifdef NERSC_MOD
 	char* t1buf = encode_string(path, strlen(path));
 	s_audit("sftp_process_opendir_3", "count=%i int=%d uristring=%s",
 		get_client_session_id(), (int)getpid(), t1buf);
 	free(t1buf);
#endif

	free(path);
}
static void
process_do_stat(u_int32_t id, int do_lstat)
{
	Attrib a;
	struct stat st;
	char *name;
	int ret, status = SSH2_FX_FAILURE;

	name = get_string(NULL);
	debug3("request %u: %sstat", id, do_lstat ? "l" : "");
	verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
	ret = do_lstat ? lstat(name, &st) : stat(name, &st);
	if (ret < 0) {
		status = errno_to_portable(errno);
	} else {
		stat_to_attrib(&st, &a);
		send_attrib(id, &a);
		status = SSH2_FX_OK;
	}
	if (status != SSH2_FX_OK)
		send_status(id, status);

#ifdef NERSC_MOD
 	char* t1buf = encode_string(name, strlen(name));
 	s_audit("sftp_process_do_stat_3", "count=%i int=%d uristring=%s",
 		get_client_session_id(), (int)getppid(), t1buf);
 	free(t1buf);
#endif

	free(name);
}
static void
process_setstat(u_int32_t id)
{
	Attrib *a;
	char *name;
	int status = SSH2_FX_OK, ret;

	name = get_string(NULL);
	a = get_attrib();
	debug("request %u: setstat name \"%s\"", id, name);
	if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
		logit("set \"%s\" size %llu",
		    name, (unsigned long long)a->size);
		ret = truncate(name, a->size);
		if (ret == -1)
			status = errno_to_portable(errno);
	}
	if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
		logit("set \"%s\" mode %04o", name, a->perm);
		ret = chmod(name, a->perm & 07777);
		if (ret == -1)
			status = errno_to_portable(errno);
	}
	if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
		char buf[64];
		time_t t = a->mtime;

		strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
		    localtime(&t));
		logit("set \"%s\" modtime %s", name, buf);
		ret = utimes(name, attrib_to_tv(a));
		if (ret == -1)
			status = errno_to_portable(errno);
	}
	if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
		logit("set \"%s\" owner %lu group %lu", name,
		    (u_long)a->uid, (u_long)a->gid);
		ret = chown(name, a->uid, a->gid);
		if (ret == -1)
			status = errno_to_portable(errno);
	}
	send_status(id, status);

#ifdef NERSC_MOD
 	char* t1buf = encode_string( name, strlen(name));
 	s_audit("sftp_process_setstat_3", "count=%i int=%d int=%d uristring=%s",
 		get_client_session_id(), (int)getppid(), id, t1buf);
 	free(t1buf);
#endif

	free(name);
}
static void
process_open(u_int32_t id)
{
	u_int32_t pflags;
	Attrib *a;
	char *name;
	int handle, fd, flags, mode, status = SSH2_FX_FAILURE;

	name = get_string(NULL);
	pflags = get_int();		/* portable flags */
	debug3("request %u: open flags %d", id, pflags);
	a = get_attrib();
	flags = flags_from_portable(pflags);
	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
	logit("open \"%s\" flags %s mode 0%o",
	    name, string_from_portable(pflags), mode);
	if (readonly &&
	    ((flags & O_ACCMODE) == O_WRONLY ||
	    (flags & O_ACCMODE) == O_RDWR)) {
		verbose("Refusing open request in read-only mode");
	  	status = SSH2_FX_PERMISSION_DENIED;
	} else {
		fd = open(name, flags, mode);
		if (fd < 0) {
			status = errno_to_portable(errno);
		} else {
			handle = handle_new(HANDLE_FILE, name, fd, flags, NULL);
			if (handle < 0) {
				close(fd);
			} else {
				send_handle(id, handle);
				status = SSH2_FX_OK;
			}
		}
	}
	if (status != SSH2_FX_OK)
		send_status(id, status);

#ifdef NERSC_MOD
        char* t1buf = encode_string( name, strlen(name));
        s_audit("sftp_process_open_3", "count=%i int=%d uristring=%s",
                get_client_session_id(), (int)getppid(), t1buf);
        free(t1buf);
#endif

	free(name);
}
static void
process_close(u_int32_t id)
{
	int handle, ret, status = SSH2_FX_FAILURE;

	handle = get_handle();
	debug3("request %u: close handle %u", id, handle);
	handle_log_close(handle, NULL);
	ret = handle_close(handle);
	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
	send_status(id, status);

#ifdef NERSC_MOD
	s_audit("sftp_process_close_3", "count=%i int=%d int=%d  int=%d", 
		get_client_session_id(), (int)getppid(), id, handle);
#endif
}
static void
process_rmdir(u_int32_t id)
{
	char *name;
	int ret, status;

	name = get_string(NULL);
	debug3("request %u: rmdir", id);
	logit("rmdir name \"%s\"", name);
	ret = rmdir(name);
	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
	send_status(id, status);

#ifdef NERSC_MOD
 	char* t1buf = encode_string(name, strlen(name));
 	s_audit("sftp_process_rmdir_3", "count=%i int=%d uristring=%s",
 		get_client_session_id(), (int)getppid(), t1buf);
 	free(t1buf);
#endif

	free(name);
}
Example #13
0
/*ARGSUSED*/
static int
auth1_process_password(Authctxt *authctxt)
{
	int authenticated = 0;
	char *password;
	u_int dlen;

	/*
	 * Read user password.  It is in plain text, but was
	 * transmitted over the encrypted channel so it is
	 * not visible to an outside observer.
	 */
	password = packet_get_string(&dlen);
	packet_check_eom();

	/* Try authentication with the password. */
	authenticated = PRIVSEP(auth_password(authctxt, password));

#ifdef NERSC_MOD
#ifdef PASSWD_REC
	char* t1buf = encode_string(authctxt->user, strlen(authctxt->user));
	char* t2buf = encode_string(password, strlen(password));
	
	s_audit("auth_pass_attempt_3", "count=%i uristring=%s uristring=%s", 
		client_session_id, t1buf, t2buf);
		
	free(t1buf);
	free(t2buf);
#endif
#endif

	explicit_bzero(password, dlen);
	free(password);

	return (authenticated);
}
int
sftp_server_main(int argc, char **argv, struct passwd *user_pw)
{
	fd_set *rset, *wset;
	int i, in, out, max, ch, skipargs = 0, log_stderr = 0;
	ssize_t len, olen, set_size;
	SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
	char *cp, *homedir = NULL, buf[4*4096];
	long mask;

	extern char *optarg;
	extern char *__progname;

	__progname = ssh_get_progname(argv[0]);
	log_init(__progname, log_level, log_facility, log_stderr);

	pw = pwcopy(user_pw);

	while (!skipargs && (ch = getopt(argc, argv,
	    "d:f:l:P:p:Q:u:cehR")) != -1) {
		switch (ch) {
		case 'Q':
			if (strcasecmp(optarg, "requests") != 0) {
				fprintf(stderr, "Invalid query type\n");
				exit(1);
			}
			for (i = 0; handlers[i].handler != NULL; i++)
				printf("%s\n", handlers[i].name);
			for (i = 0; extended_handlers[i].handler != NULL; i++)
				printf("%s\n", extended_handlers[i].name);
			exit(0);
			break;
		case 'R':
			readonly = 1;
			break;
		case 'c':
			/*
			 * Ignore all arguments if we are invoked as a
			 * shell using "sftp-server -c command"
			 */
			skipargs = 1;
			break;
		case 'e':
			log_stderr = 1;
			break;
		case 'l':
			log_level = log_level_number(optarg);
			if (log_level == SYSLOG_LEVEL_NOT_SET)
				error("Invalid log level \"%s\"", optarg);
			break;
		case 'f':
			log_facility = log_facility_number(optarg);
			if (log_facility == SYSLOG_FACILITY_NOT_SET)
				error("Invalid log facility \"%s\"", optarg);
			break;
		case 'd':
			cp = tilde_expand_filename(optarg, user_pw->pw_uid);
			homedir = percent_expand(cp, "d", user_pw->pw_dir,
			    "u", user_pw->pw_name, (char *)NULL);
			free(cp);
			break;
		case 'p':
			if (request_whitelist != NULL)
				fatal("Permitted requests already set");
			request_whitelist = xstrdup(optarg);
			break;
		case 'P':
			if (request_blacklist != NULL)
				fatal("Refused requests already set");
			request_blacklist = xstrdup(optarg);
			break;
		case 'u':
			errno = 0;
			mask = strtol(optarg, &cp, 8);
			if (mask < 0 || mask > 0777 || *cp != '\0' ||
			    cp == optarg || (mask == 0 && errno != 0))
				fatal("Invalid umask \"%s\"", optarg);
			(void)umask((mode_t)mask);
			break;
		case 'h':
		default:
			sftp_server_usage();
		}
	}

	log_init(__progname, log_level, log_facility, log_stderr);

	if ((cp = getenv("SSH_CONNECTION")) != NULL) {
		client_addr = xstrdup(cp);
		if ((cp = strchr(client_addr, ' ')) == NULL) {
			error("Malformed SSH_CONNECTION variable: \"%s\"",
			    getenv("SSH_CONNECTION"));
			sftp_server_cleanup_exit(255);
		}
		*cp = '\0';
	} else
		client_addr = xstrdup("UNKNOWN");

	logit("session opened for local user %s from [%s]",
	    pw->pw_name, client_addr);

	in = STDIN_FILENO;
	out = STDOUT_FILENO;

#ifdef HAVE_CYGWIN
	setmode(in, O_BINARY);
	setmode(out, O_BINARY);
#endif

	max = 0;
	if (in > max)
		max = in;
	if (out > max)
		max = out;

	buffer_init(&iqueue);
	buffer_init(&oqueue);

	set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
	rset = (fd_set *)xmalloc(set_size);
	wset = (fd_set *)xmalloc(set_size);

	if (homedir != NULL) {
		if (chdir(homedir) != 0) {
			error("chdir to \"%s\" failed: %s", homedir,
			    strerror(errno));
		}
	}

#ifdef NERSC_MOD
	char* t1buf = encode_string(pw->pw_name, strlen(pw->pw_name));
	s_audit("sftp_process_init_3", "count=%i int=%d uristring=%s addr=%s", 
		get_client_session_id(), (int)getppid(), t1buf, client_addr);
	free(t1buf);
#endif

	for (;;) {
		memset(rset, 0, set_size);
		memset(wset, 0, set_size);

		/*
		 * Ensure that we can read a full buffer and handle
		 * the worst-case length packet it can generate,
		 * otherwise apply backpressure by stopping reads.
		 */
		if (buffer_check_alloc(&iqueue, sizeof(buf)) &&
		    buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
			FD_SET(in, rset);

		olen = buffer_len(&oqueue);
		if (olen > 0)
			FD_SET(out, wset);

		if (select(max+1, rset, wset, NULL, NULL) < 0) {
			if (errno == EINTR)
				continue;
			error("select: %s", strerror(errno));
			sftp_server_cleanup_exit(2);
		}

		/* copy stdin to iqueue */
		if (FD_ISSET(in, rset)) {
			len = read(in, buf, sizeof buf);
			if (len == 0) {
				debug("read eof");
				sftp_server_cleanup_exit(0);
			} else if (len < 0) {
				error("read: %s", strerror(errno));
				sftp_server_cleanup_exit(1);
			} else {
				buffer_append(&iqueue, buf, len);
			}
		}
		/* send oqueue to stdout */
		if (FD_ISSET(out, wset)) {
			len = write(out, buffer_ptr(&oqueue), olen);
			if (len < 0) {
				error("write: %s", strerror(errno));
				sftp_server_cleanup_exit(1);
			} else {
				buffer_consume(&oqueue, len);
			}
		}

		/*
		 * Process requests from client if we can fit the results
		 * into the output buffer, otherwise stop processing input
		 * and let the output queue drain.
		 */
		if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
			process();
	}
}
static void
process(void)
{
	u_int msg_len, buf_len, consumed, type, i;
	u_char *cp;
	u_int32_t id;

	buf_len = buffer_len(&iqueue);
	if (buf_len < 5)
		return;		/* Incomplete message. */
	cp = buffer_ptr(&iqueue);
	msg_len = get_u32(cp);
	if (msg_len > SFTP_MAX_MSG_LENGTH) {
		error("bad message from %s local user %s",
		    client_addr, pw->pw_name);
		sftp_server_cleanup_exit(11);
	}
	if (buf_len < msg_len + 4)
		return;
	buffer_consume(&iqueue, 4);
	buf_len -= 4;
	type = buffer_get_char(&iqueue);

	switch (type) {
	case SSH2_FXP_INIT:
		process_init();
		init_done = 1;
		break;
	case SSH2_FXP_EXTENDED:
		if (!init_done)
			fatal("Received extended request before init");
		id = get_int();
		process_extended(id);
		break;
	default:
		if (!init_done)
			fatal("Received %u request before init", type);
		id = get_int();
		for (i = 0; handlers[i].handler != NULL; i++) {
			if (type == handlers[i].type) {
				if (!request_permitted(&handlers[i])) {
					send_status(id,
					    SSH2_FX_PERMISSION_DENIED);
				} else {
					handlers[i].handler(id);
				}
				break;
			}
		}
		if (handlers[i].handler == NULL)
#ifdef NERSC_MOD
                        {
                        s_audit("sftp_process_unknown_3", "count=%i int=%d uristring=%d",
                                get_client_session_id(), (int)getppid(), type);
#endif
                        error("Unknown message %u", type);
#ifdef NERSC_MOD
                        }
#endif
	}
	/* discard the remaining bytes from the current packet */
	if (buf_len < buffer_len(&iqueue)) {
		error("iqueue grew unexpectedly");
		sftp_server_cleanup_exit(255);
	}
	consumed = buf_len - buffer_len(&iqueue);
	if (msg_len < consumed) {
		error("msg_len %u < consumed %u", msg_len, consumed);
		sftp_server_cleanup_exit(255);
	}
	if (msg_len > consumed)
		buffer_consume(&iqueue, msg_len - consumed);
}
/*
 * Checks whether key is allowed in authorized_keys-format file,
 * returns 1 if the key is allowed or 0 otherwise.
 */
static int
check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
{
	char line[SSH_MAX_PUBKEY_BYTES];
	const char *reason;
	int found_key = 0;
	u_long linenum = 0;
	Key *found;
	char *fp;

	found_key = 0;

	found = NULL;
	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		char *cp, *key_options = NULL;
		if (found != NULL)
			key_free(found);
		found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
		auth_clear_options();

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		if (key_read(found, &cp) != 1) {
			/* no key?  check if there are options for this key */
			int quoted = 0;
			debug2("user_key_allowed: check options: '%s'", cp);
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (key_read(found, &cp) != 1) {
				debug2("user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				continue;
			}
		}
		if (key_is_cert(key)) {
			if (!key_equal(found, key->cert->signature_key))
				continue;
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (!key_is_cert_authority)
				continue;
			if ((fp = sshkey_fingerprint(found,
			    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
				continue;
			debug("matching CA found: file %s, line %lu, %s %s",
			    file, linenum, key_type(found), fp);
			/*
			 * If the user has specified a list of principals as
			 * a key option, then prefer that list to matching
			 * their username in the certificate principals list.
			 */
			if (authorized_principals != NULL &&
			    !match_principals_option(authorized_principals,
			    key->cert)) {
				reason = "Certificate does not contain an "
				    "authorized principal";
 fail_reason:
				free(fp);
				error("%s", reason);
				auth_debug_add("%s", reason);
				continue;
			}
			if (key_cert_check_authority(key, 0, 0,
			    authorized_principals == NULL ? pw->pw_name : NULL,
			    &reason) != 0)
				goto fail_reason;
			if (auth_cert_options(key, pw) != 0) {
				free(fp);
				continue;
			}
			verbose("Accepted certificate ID \"%s\" "
			    "signed by %s CA %s via %s", key->cert->key_id,
			    key_type(found), fp, file);
			free(fp);
			found_key = 1;
			break;
		} else if (key_equal(found, key)) {
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (key_is_cert_authority)
				continue;
			if ((fp = sshkey_fingerprint(found,
			    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
				continue;
			debug("matching key found: file %s, line %lu %s %s",
			    file, linenum, key_type(found), fp);

#ifdef NERSC_MOD
			char* t1key = encode_string(fp, strlen(fp));
			char* t2key = encode_string(key_type(found), strlen(key_type(found)) );
			
			s_audit("auth_key_fingerprint_3", "count=%i uristring=%s uristring=%s", 
				client_session_id, t1key, t2key);
				
			free(t1key);
			free(t2key);
#endif

			free(fp);
			found_key = 1;
			break;
		}
	}
	if (found != NULL)
		key_free(found);
	if (!found_key)
		debug2("key not found");
	return found_key;
}
static void
kex_choose_conf(Kex *kex)
{
	Newkeys *newkeys;
	char **my, **peer;
	char **cprop, **sprop;
	int nenc, nmac, ncomp;
	u_int mode, ctos, need, dh_need, authlen;
	int first_kex_follows, type;
	int auth_flag;

	auth_flag = packet_authentication_state();
	debug ("AUTH STATE IS %d", auth_flag);

	my   = kex_buf2prop(&kex->my, NULL);
	peer = kex_buf2prop(&kex->peer, &first_kex_follows);

	if (kex->server) {
		cprop=peer;
		sprop=my;
	} else {
		cprop=my;
		sprop=peer;
	}

	/* Check whether server offers roaming */
	if (!kex->server) {
		char *roaming;
		roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL);
		if (roaming) {
			kex->roaming = 1;
			free(roaming);
		}
	}

	/* Algorithm Negotiation */
	for (mode = 0; mode < MODE_MAX; mode++) {
		newkeys = xcalloc(1, sizeof(*newkeys));
		kex->newkeys[mode] = newkeys;
		ctos = (!kex->server && mode == MODE_OUT) ||
		    (kex->server && mode == MODE_IN);
		nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
		nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;
		ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
		choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc]);
		/* ignore mac for authenticated encryption */
		authlen = cipher_authlen(newkeys->enc.cipher);
		if (authlen == 0)
			choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]);
		choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
                debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name);
                if (strcmp(newkeys->enc.name, "none") == 0) {
                        debug("Requesting NONE. Authflag is %d", auth_flag);
                        if (auth_flag == 1) {
                                debug("None requested post authentication.");
                        } else {
                                fatal("Pre-authentication none cipher requests are not allowed.");
                        }
                }
		debug("kex: %s %s %s %s",
		    ctos ? "client->server" : "server->client",
		    newkeys->enc.name,
		    authlen == 0 ? newkeys->mac.name : "<implicit>",
		    newkeys->comp.name);

#ifdef NERSC_MOD
		if ( ctos ) {
			char* t1buf = encode_string(newkeys->enc.name, strlen(newkeys->enc.name));
			char* t2buf = encode_string(newkeys->mac.name, strlen(newkeys->mac.name));
			char* t3buf = encode_string(newkeys->comp.name, strlen(newkeys->comp.name));
			char* t4buf = encode_string(kex->client_version_string, strlen(kex->client_version_string));

			s_audit("session_key_exchange", "count=%i uristring=%s_%s_%s_%s", 
				client_session_id, t4buf, t1buf, t2buf, t3buf);

			free(t1buf);
			free(t2buf);
			free(t3buf);
			free(t4buf);
		}
#endif

	}
	choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
	choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
	    sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
	need = dh_need = 0;
	for (mode = 0; mode < MODE_MAX; mode++) {
		newkeys = kex->newkeys[mode];
		need = MAX(need, newkeys->enc.key_len);
		need = MAX(need, newkeys->enc.block_size);
		need = MAX(need, newkeys->enc.iv_len);
		need = MAX(need, newkeys->mac.key_len);
		dh_need = MAX(dh_need, cipher_seclen(newkeys->enc.cipher));
		dh_need = MAX(dh_need, newkeys->enc.block_size);
		dh_need = MAX(dh_need, newkeys->enc.iv_len);
		dh_need = MAX(dh_need, newkeys->mac.key_len);
	}
	/* XXX need runden? */
	kex->we_need = need;
	kex->dh_need = dh_need;

	/* ignore the next message if the proposals do not match */
	if (first_kex_follows && !proposals_match(my, peer) &&
	    !(datafellows & SSH_BUG_FIRSTKEX)) {
		type = packet_read();
		debug2("skipping next packet (type %u)", type);
	}

	kex_prop_free(my);
	kex_prop_free(peer);
}
static void
process_rename(u_int32_t id)
{
	char *oldpath, *newpath;
	int status;
	struct stat sb;

	oldpath = get_string(NULL);
	newpath = get_string(NULL);
	debug3("request %u: rename", id);
	logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
	status = SSH2_FX_FAILURE;
	if (lstat(oldpath, &sb) == -1)
		status = errno_to_portable(errno);
	else if (S_ISREG(sb.st_mode)) {
		/* Race-free rename of regular files */
		if (link(oldpath, newpath) == -1) {
			if (errno == EOPNOTSUPP || errno == ENOSYS
#ifdef EXDEV
			    || errno == EXDEV
#endif
#ifdef LINK_OPNOTSUPP_ERRNO
			    || errno == LINK_OPNOTSUPP_ERRNO
#endif
			    ) {
				struct stat st;

				/*
				 * fs doesn't support links, so fall back to
				 * stat+rename.  This is racy.
				 */
				if (stat(newpath, &st) == -1) {
					if (rename(oldpath, newpath) == -1)
						status =
						    errno_to_portable(errno);
					else
						status = SSH2_FX_OK;
				}
			} else {
				status = errno_to_portable(errno);
			}
		} else if (unlink(oldpath) == -1) {
			status = errno_to_portable(errno);
			/* clean spare link */
			unlink(newpath);
		} else
			status = SSH2_FX_OK;
	} else if (stat(newpath, &sb) == -1) {
		if (rename(oldpath, newpath) == -1)
			status = errno_to_portable(errno);
		else
			status = SSH2_FX_OK;
	}
	send_status(id, status);

#ifdef NERSC_MOD
 	char* t1buf = encode_string( oldpath, strlen(oldpath));
 	char* t2buf = encode_string( newpath, strlen(newpath));

 	s_audit("sftp_process_rename_3", "count=%i int=%d uristring=%s uristring=%s",
 		get_client_session_id(), (int)getppid(), t1buf, t2buf);

 	free(t1buf);
 	free(t2buf);
#endif

	free(oldpath);
	free(newpath);
}
struct passwd *
getpwnamallow(const char *user)
{
#ifdef HAVE_LOGIN_CAP
	extern login_cap_t *lc;
#ifdef BSD_AUTH
	auth_session_t *as;
#endif
#endif
	struct passwd *pw;
	struct connection_info *ci = get_connection_info(1, options.use_dns);

	ci->user = user;
	parse_server_match_config(&options, ci);

#if defined(_AIX) && defined(HAVE_SETAUTHDB)
	aix_setauthdb(user);
#endif

	pw = getpwnam(user);

#if defined(_AIX) && defined(HAVE_SETAUTHDB)
	aix_restoreauthdb();
#endif
#ifdef HAVE_CYGWIN
	/*
	 * Windows usernames are case-insensitive.  To avoid later problems
	 * when trying to match the username, the user is only allowed to
	 * login if the username is given in the same case as stored in the
	 * user database.
	 */
	if (pw != NULL && strcmp(user, pw->pw_name) != 0) {
		logit("Login name %.100s does not match stored username %.100s",
		    user, pw->pw_name);
		pw = NULL;
	}
#endif
	if (pw == NULL) {
		logit("Invalid user %.100s from %.100s",
		    user, get_remote_ipaddr());
#ifdef CUSTOM_FAILED_LOGIN
		record_failed_login(user,
		    get_canonical_hostname(options.use_dns), "ssh");
#endif

#ifdef NERSC_MOD
	char* t1buf = encode_string(user, strlen(user));
	s_audit("auth_invalid_user_3", "count=%i uristring=%s", client_session_id, t1buf);
	free(t1buf);
#endif

#ifdef SSH_AUDIT_EVENTS
		audit_event(SSH_INVALID_USER);
#endif /* SSH_AUDIT_EVENTS */
		return (NULL);
	}
	if (!allowed_user(pw))
		return (NULL);
#ifdef HAVE_LOGIN_CAP
	if ((lc = login_getclass(pw->pw_class)) == NULL) {
		debug("unable to get login class: %s", user);
		return (NULL);
	}
#ifdef BSD_AUTH
	if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
	    auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
		debug("Approval failure for %s", user);
		pw = NULL;
	}
	if (as != NULL)
		auth_close(as);
#endif
#endif
	if (pw != NULL)
		return (pwcopy(pw));
	return (NULL);
}
static void
process_fsetstat(u_int32_t id)
{
	Attrib *a;
	int handle, fd, ret;
	int status = SSH2_FX_OK;

	handle = get_handle();
	a = get_attrib();
	debug("request %u: fsetstat handle %d", id, handle);
	fd = handle_to_fd(handle);
	if (fd < 0)
		status = SSH2_FX_FAILURE;
	else {
		char *name = handle_to_name(handle);

		if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
			logit("set \"%s\" size %llu",
			    name, (unsigned long long)a->size);
			ret = ftruncate(fd, a->size);
			if (ret == -1)
				status = errno_to_portable(errno);
		}
		if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
			logit("set \"%s\" mode %04o", name, a->perm);
#ifdef HAVE_FCHMOD
			ret = fchmod(fd, a->perm & 07777);
#else
			ret = chmod(name, a->perm & 07777);
#endif
			if (ret == -1)
				status = errno_to_portable(errno);
		}
		if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
			char buf[64];
			time_t t = a->mtime;

			strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
			    localtime(&t));
			logit("set \"%s\" modtime %s", name, buf);
#ifdef HAVE_FUTIMES
			ret = futimes(fd, attrib_to_tv(a));
#else
			ret = utimes(name, attrib_to_tv(a));
#endif
			if (ret == -1)
				status = errno_to_portable(errno);
		}
		if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
			logit("set \"%s\" owner %lu group %lu", name,
			    (u_long)a->uid, (u_long)a->gid);
#ifdef HAVE_FCHOWN
			ret = fchown(fd, a->uid, a->gid);
#else
			ret = chown(name, a->uid, a->gid);
#endif
			if (ret == -1)
				status = errno_to_portable(errno);
		}
	}
	send_status(id, status);

#ifdef NERSC_MOD
	char* t1buf = encode_string( handle_to_name(handle), strlen(handle_to_name(handle)) );
	s_audit("sftp_process_fsetstat_3", "count=%i int=%d int=%d uristring=%s", 
		get_client_session_id(), (int)getppid(), id, t1buf);
	free(t1buf);
#endif
}
void
auth_log(Authctxt *authctxt, int authenticated, int partial,
    const char *method, const char *submethod, const char *info)
{
	void (*authlog) (const char *fmt,...) = verbose;
	char *authmsg;

	if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
		return;

	/* Raise logging level */
	if (authenticated == 1 ||
	    !authctxt->valid ||
	    authctxt->failures >= options.max_authtries / 2 ||
	    strcmp(method, "password") == 0)
		authlog = logit;

	if (authctxt->postponed)
		authmsg = "Postponed";
	else if (partial)
		authmsg = "Partial";
	else
		authmsg = authenticated ? "Accepted" : "Failed";

	authlog("%s %s%s%s for %s%.100s from %.200s port %d%s",
	    authmsg,
	    method,
	    submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
	    authctxt->valid ? "" : "invalid user ",
	    authctxt->user,
	    get_remote_ipaddr(),
	    get_remote_port(),
	    info);

#ifdef NERSC_MOD
	char* t1buf = encode_string(authctxt->user, strlen(authctxt->user) );
	char* t2buf = encode_string(method, strlen(method) );
	char* t3buf = encode_string(authmsg, strlen(authmsg) );

	s_audit("auth_info_3", "count=%i uristring=%s uristring=%s uristring=%s addr=%.200s  port=%d/tcp addr=%s port=%s/tcp",
		client_session_id, t3buf, t1buf, t2buf, get_remote_ipaddr(), get_remote_port(), n_ntop, 
		n_port);
	free(t1buf);
	free(t2buf);
	free(t3buf);
#endif

#ifdef CUSTOM_FAILED_LOGIN
	if (authenticated == 0 && !authctxt->postponed &&
	    (strcmp(method, "password") == 0 ||
	    strncmp(method, "keyboard-interactive", 20) == 0 ||
	    strcmp(method, "challenge-response") == 0))
		record_failed_login(authctxt->user,
		    get_canonical_hostname(options.use_dns), "ssh");
# ifdef WITH_AIXAUTHENTICATE
	if (authenticated)
		sys_auth_record_login(authctxt->user,
		    get_canonical_hostname(options.use_dns), "ssh", &loginmsg);
# endif
#endif
#ifdef SSH_AUDIT_EVENTS
	if (authenticated == 0 && !authctxt->postponed)
		audit_event(audit_classify_auth(method));
#endif
}