static int filestore_verify_host_key(sftp_keystore_t *store, pool *p, const char *user, const char *host_fqdn, const char *host_user, unsigned char *key_data, uint32_t key_len) { struct filestore_key *key = NULL; struct filestore_data *store_data = store->keystore_data; int res = -1; if (!store_data->path) { errno = EPERM; return -1; } /* XXX Note that this will scan the file from the beginning, each time. * There's room for improvement; perhaps mmap() the file into memory? */ key = filestore_get_key(store, p); while (key) { int ok; pr_signals_handle(); ok = sftp_keys_compare_keys(p, key_data, key_len, key->key_data, key->key_datalen); if (ok != TRUE) { if (ok == -1) { (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "error comparing keys from '%s': %s", store_data->path, strerror(errno)); } } else { /* XXX Verify that the user and the host_user match?? */ res = 0; break; } key = filestore_get_key(store, p); } if (res == 0) { pr_trace_msg(trace_channel, 10, "found matching public key for host '%s' " "in '%s'", host_fqdn, store_data->path); } if (pr_fsio_lseek(store_data->fh, 0, SEEK_SET) < 0) { (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "error seeking to start of '%s': %s", store_data->path, strerror(errno)); return -1; } store_data->lineno = 0; return res; }
static array_header *counter_file_read(pr_fh_t *fh) { char buf[PR_TUNABLE_BUFFER_SIZE]; array_header *ids = make_array(counter_pool, 0, sizeof(int)); /* Read the list of IDs in the CounterFile into an array. */ if (counter_file_lock(fh, LOCK_SH) < 0) { (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION, "error read-locking CounterFile '%s': %s", fh->fh_path, strerror(errno)); } if (pr_fsio_lseek(fh, 0, SEEK_SET) < 0) { int xerrno = errno; counter_file_lock(fh, LOCK_UN); errno = xerrno; return NULL; } memset(buf, '\0', sizeof(buf)); while (pr_fsio_gets(buf, sizeof(buf), fh) != NULL) { int id; pr_signals_handle(); id = atoi(buf); if (id < 0) { continue; } *((int *) push_array(ids)) = id; } if (counter_file_lock(fh, LOCK_UN) < 0) { (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION, "error unlocking CounterFile '%s': %s", fh->fh_path, strerror(errno)); } return ids; }
static int filestore_verify_user_key(sftp_keystore_t *store, pool *p, const char *user, unsigned char *key_data, uint32_t key_len) { struct filestore_key *key = NULL; struct filestore_data *store_data = store->keystore_data; unsigned int count = 0; int res = -1; if (!store_data->path) { errno = EPERM; return -1; } /* XXX Note that this will scan the file from the beginning, each time. * There's room for improvement; perhaps mmap() the file into memory? */ key = filestore_get_key(store, p); while (key) { int ok; pr_signals_handle(); count++; ok = sftp_keys_compare_keys(p, key_data, key_len, key->key_data, key->key_datalen); if (ok != TRUE) { if (ok == -1) { (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "error comparing keys from '%s': %s", store_data->path, strerror(errno)); } else { pr_trace_msg(trace_channel, 10, "failed to match key #%u from file '%s'", count, store_data->path); } } else { /* If we are configured to check for Subject headers, and if the file key * has a Subject header, and that header value does not match the * logging in user, then continue looking. */ if ((sftp_opts & SFTP_OPT_MATCH_KEY_SUBJECT) && key->subject != NULL) { if (strcmp(key->subject, user) != 0) { (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "found matching key for user '%s' in '%s', but Subject " "header ('%s') does not match, skipping key", user, store_data->path, key->subject); } else { res = 0; break; } } else { res = 0; break; } } key = filestore_get_key(store, p); } if (res == 0) { pr_trace_msg(trace_channel, 10, "found matching public key for user '%s' " "in '%s'", user, store_data->path); } if (pr_fsio_lseek(store_data->fh, 0, SEEK_SET) < 0) { (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "error seeking to start of '%s': %s", store_data->path, strerror(errno)); return -1; } store_data->lineno = 0; return res; }
static int counter_file_write(pr_fh_t *fh, array_header *ids) { register unsigned int i; int *elts; /* Write the list of IDs in the given array to the CounterFile, * overwriting any previous values. */ if (counter_file_lock(fh, LOCK_EX) < 0) { (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION, "error write-locking CounterFile '%s': %s", fh->fh_path, strerror(errno)); } if (pr_fsio_lseek(fh, 0, SEEK_SET) < 0) { int xerrno = errno; counter_file_lock(fh, LOCK_UN); errno = xerrno; return -1; } elts = (int *) ids->elts; for (i = 0; i < ids->nelts; i++) { char buf[32]; pr_signals_handle(); /* Skip any negative IDs. This small hack allows for IDs to be * effectively removed from the list. */ if (elts[i] < 0) { continue; } memset(buf, '\0', sizeof(buf)); snprintf(buf, sizeof(buf), "%d\n", elts[i]); buf[sizeof(buf)-1] = '\0'; buf[strlen(buf)-1] = '\0'; if (pr_fsio_puts(buf, fh) < 0) { int xerrno = errno; counter_file_lock(fh, LOCK_UN); errno = xerrno; return -1; } } if (pr_fsio_ftruncate(fh, 0) < 0) { int xerrno = errno; counter_file_lock(fh, LOCK_UN); errno = xerrno; return -1; } if (counter_file_lock(fh, LOCK_SH) < 0) { (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION, "error unlocking CounterFile '%s': %s", fh->fh_path, strerror(errno)); } return 0; }