/* * [MS-DFSC]: REQ_GET_DFS_REFERRAL * * Determines the referral type based on the specified path: * * Domain referral: * "" * * DC referral: * \<domain> * * Sysvol referral: * \<domain>\SYSVOL * \<domain>\NETLOGON * * Root referral: * \<domain>\<dfsname> * \<server>\<dfsname> * * Link referral: * \<domain>\<dfsname>\<linkpath> * \<server>\<dfsname>\<linkpath> */ static dfs_reftype_t smb_dfs_get_reftype(const char *path) { smb_unc_t unc; dfs_reftype_t reftype = 0; if (*path == '\0') return (DFS_REFERRAL_DOMAIN); if (smb_unc_init(path, &unc) != 0) return (DFS_REFERRAL_INVALID); if (unc.unc_path != NULL) { reftype = DFS_REFERRAL_LINK; } else if (unc.unc_share != NULL) { if ((smb_strcasecmp(unc.unc_share, "SYSVOL", 0) == 0) || (smb_strcasecmp(unc.unc_share, "NETLOGON", 0) == 0)) { reftype = DFS_REFERRAL_SYSVOL; } else { reftype = DFS_REFERRAL_ROOT; } } else if (unc.unc_server != NULL) { reftype = DFS_REFERRAL_DC; } smb_unc_free(&unc); return (reftype); }
/* * Takes a DFS path in UNC format (dfs_path) and parse it into a dfs_path_t * structure. * * dfs_path_free() MUST be called to free the allocated memory in this * function. * * Returns: * * ERROR_INVALID_PARAMETER path is not a valid UNC or not valid for the * specified object type * ERROR_NOT_ENOUGH_MEMORY not enough memory to peform the parse * ERROR_NOT_FOUND namespace specified does not exist */ uint32_t dfs_path_parse(dfs_path_t *path, const char *dfs_path, uint32_t path_type) { char rootdir[DFS_PATH_MAX]; smb_unc_t *unc; uint32_t status = ERROR_SUCCESS; int rc; bzero(path, sizeof (dfs_path_t)); unc = &path->p_unc; rc = smb_unc_init(dfs_path, unc); switch (rc) { case EINVAL: return (ERROR_INVALID_PARAMETER); case ENOMEM: return (ERROR_NOT_ENOUGH_MEMORY); default: break; } if (dfs_namespace_path(unc->unc_share, rootdir, DFS_PATH_MAX) != ERROR_SUCCESS) { smb_unc_free(unc); return (ERROR_NOT_FOUND); } if (path_type == DFS_OBJECT_ANY) path->p_type = (unc->unc_path != NULL) ? DFS_OBJECT_LINK : DFS_OBJECT_ROOT; else path->p_type = path_type; switch (path->p_type) { case DFS_OBJECT_LINK: if ((unc->unc_path == NULL) || (*unc->unc_path == '\0')) status = ERROR_NOT_FOUND; else (void) snprintf(path->p_fspath, sizeof (path->p_fspath), "%s/%s", rootdir, unc->unc_path); break; case DFS_OBJECT_ROOT: if (unc->unc_path == NULL) (void) strlcpy(path->p_fspath, rootdir, sizeof (path->p_fspath)); else status = ERROR_INVALID_PARAMETER; break; default: status = ERROR_INVALID_PARAMETER; } if (status != ERROR_SUCCESS) smb_unc_free(unc); return (status); }
/* * valid DFS I/O path: * * \server-or-domain\share * \server-or-domain\share\path * * All the returned errors by this function needs to be * checked against Windows. */ static int smb_pathname_dfs_preprocess(smb_request_t *sr, char *path, size_t pathsz) { smb_unc_t unc; char *linkpath; int rc; if (sr->tid_tree == NULL) return (0); if ((rc = smb_unc_init(path, &unc)) != 0) return (rc); if (smb_strcasecmp(unc.unc_share, sr->tid_tree->t_sharename, 0)) { smb_unc_free(&unc); return (EINVAL); } linkpath = unc.unc_path; (void) snprintf(path, pathsz, "/%s", (linkpath) ? linkpath : ""); smb_unc_free(&unc); return (0); }