char *dir_canonical_vpath(pool *p, const char *path) { char buf[PR_TUNABLE_PATH_MAX + 1] = {'\0'}; char work[PR_TUNABLE_PATH_MAX + 1] = {'\0'}; if (p == NULL || path == NULL) { errno = EINVAL; return NULL; } if (*path == '~') { if (pr_fs_interpolate(path, work, sizeof(work)-1) != 1) { if (pr_fs_dircat(work, sizeof(work), pr_fs_getvwd(), path) < 0) { return NULL; } } } else { if (pr_fs_dircat(work, sizeof(work), pr_fs_getvwd(), path) < 0) { return NULL; } } pr_fs_clean_path(work, buf, sizeof(buf)-1); return pstrdup(p, buf); }
/* dir_best_path() creates the "most" fully canonicalized path possible * (i.e. if path components at the end don't exist, they are ignored). */ char *dir_best_path(pool *p, const char *path) { char workpath[PR_TUNABLE_PATH_MAX + 1] = {'\0'}; char realpath_buf[PR_TUNABLE_PATH_MAX + 1] = {'\0'}; char *target = NULL, *ntarget; int fini = 0; if (*path == '~') { if (pr_fs_interpolate(path, workpath, sizeof(workpath)-1) != 1) { if (pr_fs_dircat(workpath, sizeof(workpath), pr_fs_getcwd(), path) < 0) return NULL; } } else { if (pr_fs_dircat(workpath, sizeof(workpath), pr_fs_getcwd(), path) < 0) return NULL; } pr_fs_clean_path(pstrdup(p, workpath), workpath, sizeof(workpath)-1); while (!fini && *workpath) { if (pr_fs_resolve_path(workpath, realpath_buf, sizeof(realpath_buf)-1, 0) != -1) break; ntarget = strrchr(workpath, '/'); if (ntarget) { if (target) { if (pr_fs_dircat(workpath, sizeof(workpath), workpath, target) < 0) return NULL; } target = ntarget; *target++ = '\0'; } else fini++; } if (!fini && *workpath) { if (target) { if (pr_fs_dircat(workpath, sizeof(workpath), realpath_buf, target) < 0) return NULL; } else sstrncpy(workpath, realpath_buf, sizeof(workpath)); } else { if (pr_fs_dircat(workpath, sizeof(workpath), "/", target) < 0) return NULL; } return pstrdup(p, workpath); }
/* Takes a directory and returns its absolute version. ~username references * are appropriately interpolated. "Absolute" includes a _full_ reference * based on the root directory, not upon a chrooted dir. */ char *dir_abs_path(pool *p, const char *path, int interpolate) { char *res = NULL; if (p == NULL || path == NULL) { errno = EINVAL; return NULL; } if (interpolate) { char buf[PR_TUNABLE_PATH_MAX+1]; memset(buf, '\0', sizeof(buf)); switch (pr_fs_interpolate(path, buf, sizeof(buf)-1)) { case -1: return NULL; case 0: /* Do nothing; path exists */ break; case 1: /* Interpolation occurred; make a copy of the interpolated path. */ path = pstrdup(p, buf); break; } } if (*path != '/') { if (session.chroot_path) { res = pdircat(p, session.chroot_path, pr_fs_getcwd(), path, NULL); } else { res = pdircat(p, pr_fs_getcwd(), path, NULL); } } else { if (session.chroot_path) { if (strncmp(path, session.chroot_path, strlen(session.chroot_path)) != 0) { res = pdircat(p, session.chroot_path, path, NULL); } else { res = pstrdup(p, path); } } else { res = pstrdup(p, path); } } return res; }
static sftp_keystore_t *filestore_open(pool *parent_pool, int requested_key_type, const char *store_info, const char *user) { int xerrno; sftp_keystore_t *store; pool *filestore_pool; struct filestore_data *store_data; pr_fh_t *fh; char buf[PR_TUNABLE_PATH_MAX+1], *path; struct stat st; filestore_pool = make_sub_pool(parent_pool); pr_pool_tag(filestore_pool, "SFTP File-based Keystore Pool"); store = pcalloc(filestore_pool, sizeof(sftp_keystore_t)); store->keystore_pool = filestore_pool; /* Open the file. The given path (store_info) may need to be * interpolated. */ session.user = (char *) user; memset(buf, '\0', sizeof(buf)); switch (pr_fs_interpolate(store_info, buf, sizeof(buf)-1)) { case 1: /* Interpolate occurred; make a copy of the interpolated path. */ path = pstrdup(filestore_pool, buf); break; default: /* Otherwise, use the path as is. */ path = pstrdup(filestore_pool, store_info); break; } session.user = NULL; PRIVS_ROOT fh = pr_fsio_open(path, O_RDONLY|O_NONBLOCK); xerrno = errno; PRIVS_RELINQUISH if (fh == NULL) { destroy_pool(filestore_pool); errno = xerrno; return NULL; } if (pr_fsio_set_block(fh) < 0) { xerrno = errno; destroy_pool(filestore_pool); (void) pr_fsio_close(fh); errno = xerrno; return NULL; } /* Stat the opened file to determine the optimal buffer size for IO. */ memset(&st, 0, sizeof(st)); if (pr_fsio_fstat(fh, &st) < 0) { xerrno = errno; destroy_pool(filestore_pool); (void) pr_fsio_close(fh); errno = xerrno; return NULL; } if (S_ISDIR(st.st_mode)) { destroy_pool(filestore_pool); (void) pr_fsio_close(fh); errno = EISDIR; return NULL; } fh->fh_iosz = st.st_blksize; store_data = pcalloc(filestore_pool, sizeof(struct filestore_data)); store->keystore_data = store_data; store_data->path = path; store_data->fh = fh; store_data->lineno = 0; store->store_ktypes = requested_key_type; switch (requested_key_type) { case SFTP_SSH2_HOST_KEY_STORE: store->verify_host_key = filestore_verify_host_key; break; case SFTP_SSH2_USER_KEY_STORE: store->verify_user_key = filestore_verify_user_key; break; } store->store_close = filestore_close; return store; }