Exemplo n.º 1
0
Arquivo: server.c Projeto: B1NG0/cifs
NTSTATUS
SMBReleaseServer(
    SMBHANDLE inConnection)
{
    refcount_t refcount;

    refcount = OSAtomicDecrement32(&inConnection->refcount);
    if (refcount == 0) {
        smb_ctx_done(inConnection->context);
        free(inConnection);
    }

    return STATUS_SUCCESS;
}
Exemplo n.º 2
0
Arquivo: netfs.c Projeto: B1NG0/cifs
/*
 * SMBNetFsCreateSessionRef
 *
 * Load the smbfs kext if need, initialize anything needed by the library  and
 * create a session reference structure, the first element must have our schema
 * as a CFStringRef.
 */
int32_t 
SMBNetFsCreateSessionRef(SMBHANDLE *outConnection)
{
	void *hContext;
	int error;
	
	*outConnection = NULL;
	/* Need to initialize the library and load the kext */
	error = smb_load_library();
	if (error) {
		return error;
	}
	/* create_smb_ctx can only fail because of an allocation failure */
	hContext = create_smb_ctx();
	if (hContext == NULL) {
		return ENOMEM;
	}
	*outConnection = SMBAllocateAndSetContext(hContext);
	if (*outConnection == NULL) {
        smb_ctx_done(hContext);
		return ENOMEM;
	}
	return 0;
}
Exemplo n.º 3
0
/*
 * Would prefer to do all of this as the user that mounted the volume, but it
 * seems the sysctlbyfsid requires you to be root. So do the sysctlbyfsid as
 * root and everything else as the user.
 */
int smb_remount_with_fsid(fsid_t fsid)
{
    int error, error2;
    struct smb_ctx *ctx = NULL;
    struct smb_remount_info remountInfo;
    uid_t rootUID = geteuid();

    /* Get the remount information need for the remount */
    memset(&remountInfo, 0, sizeof(remountInfo));
    error = SysctlRemountInfo(fsid, &remountInfo);
    if (error) {
        goto done;
    }

    smb_log_info("%s: mount url smb:%s", ASL_LEVEL_DEBUG, __FUNCTION__,
                 remountInfo.mntURL);
    smb_log_info("%s: client principal name %s", ASL_LEVEL_DEBUG, __FUNCTION__,
                 remountInfo.mntClientPrincipalName);
    smb_log_info("%s: client principal name type %d", ASL_LEVEL_DEBUG, __FUNCTION__,
                 remountInfo.mntClientPrincipalNameType);
    smb_log_info("%s: authorization flags 0x%x", ASL_LEVEL_DEBUG, __FUNCTION__,
                 remountInfo.mntAuthFlags);
    smb_log_info("%s: owner of mount point %d", ASL_LEVEL_DEBUG, __FUNCTION__,
                 remountInfo.mntOwner);

    /* Switch to the user that owns the mount */
    error2 = seteuid(remountInfo.mntOwner);
    if (error2) {
        smb_log_info("%s: seteuid failed %d for mntOwner", ASL_LEVEL_ERR,
                     __FUNCTION__, error2);
        goto done;
    }

    error = create_smb_ctx_with_url(&ctx, remountInfo.mntURL);
    if (error) {
        smb_log_info("%s: Could create ctx from url smb:%s", ASL_LEVEL_ERR,
                     __FUNCTION__, remountInfo.mntURL);
        error2 = seteuid(rootUID);
        if (error2) {
            smb_log_info("%s: seteuid failed %d for rootUID", ASL_LEVEL_ERR,
                         __FUNCTION__, error2);
        }

        goto done;
    }

    error = GetRootShareConnection(ctx, remountInfo.mntURL,
                                   remountInfo.mntAuthFlags,
                                   remountInfo.mntClientPrincipalName,
                                   remountInfo.mntClientPrincipalNameType,
                                   remountInfo.mntDeadTimer);
    if (!error) {
        struct smb_ctx *dfs_ctx = NULL;

        /*
         * XXX - Need to handle the DfsRoot remount case, we should check to
         * see if this is just a DfsRoot, if so then continue with the remount
         * because we found a different domain control to access.
         */
        error = checkForDfsReferral(ctx, &dfs_ctx, NULL, NULL);
        if (error ||
                (ctx == dfs_ctx) ||
                (dfs_ctx == NULL)) {
            error2 = seteuid(rootUID);
            if (error2) {
                smb_log_info("%s: seteuid failed %d for rootUID", ASL_LEVEL_ERR,
                             __FUNCTION__, error2);
            }

            goto done;
        }

        smb_ctx_done(ctx);
        ctx = dfs_ctx;
    }

    error2 = seteuid(rootUID);
    if (error2) {
        smb_log_info("%s: seteuid failed %d for rootUID", ASL_LEVEL_ERR,
                     __FUNCTION__, error2);
        goto done;
    }

    if (error) {
        goto done;
    }

    if (smb_tree_conn_fstype(ctx) == SMB_FS_FAT) {
        smb_log_info("%s: Could remount url smb:%s found a fat file system",
                     ASL_LEVEL_ERR,  __FUNCTION__, remountInfo.mntURL);
        error = ENOTSUP;
        goto done;
    }

    if (!error) {
        error = SysctlRemountFS(fsid, ctx->ct_fd);
    }

done:
    if (ctx) {
        error2 = seteuid(remountInfo.mntOwner);
        if (error2) {
            smb_log_info("%s: seteuid failed %d for mntOwner", ASL_LEVEL_ERR,
                         __FUNCTION__, error2);
        }

        smb_ctx_done(ctx);

        error2 = seteuid(rootUID);
        if (error2) {
            smb_log_info("%s: seteuid failed %d for rootUID", ASL_LEVEL_ERR,
                         __FUNCTION__, error2);
        }
    }

    if (error) {
        smb_log_info("%s: remount failed for url %s with error = %d",
                     ASL_LEVEL_ERR, __FUNCTION__, remountInfo.mntURL, error);
    }

    return error;
}
Exemplo n.º 4
0
int
main(int argc, char *argv[])
{
	struct iovec *iov;
	unsigned int iovlen;
	struct smb_ctx sctx, *ctx = &sctx;
	struct stat st;
#ifdef APPLE
	extern void dropsuid();
	extern int loadsmbvfs();
#else
	struct xvfsconf vfc;
#endif
	char *next, *p, *val;
	int opt, error, mntflags, caseopt, fd;
	uid_t uid;
	gid_t gid;
	mode_t dir_mode, file_mode;
	char errmsg[255] = { 0 };

	iov = NULL;
	iovlen = 0;
	fd = 0;
	uid = (uid_t)-1;
	gid = (gid_t)-1;
	caseopt = 0;
	file_mode = 0;
	dir_mode = 0;

#ifdef APPLE
	dropsuid();
#endif
	if (argc == 2) {
		if (strcmp(argv[1], "-h") == 0) {
			usage();
		}
	}
	if (argc < 3)
		usage();

#ifdef APPLE
	error = loadsmbvfs();
#else
	error = getvfsbyname(smbfs_vfsname, &vfc);
	if (error) {
		if (kldload(smbfs_vfsname) < 0)
			err(EX_OSERR, "kldload(%s)", smbfs_vfsname);
		error = getvfsbyname(smbfs_vfsname, &vfc);
	}
#endif
	if (error)
		errx(EX_OSERR, "SMB filesystem is not available");

	if (smb_lib_init() != 0)
		exit(1);

	mntflags = error = 0;

	caseopt = SMB_CS_NONE;

	if (smb_ctx_init(ctx, argc, argv, SMBL_SHARE, SMBL_SHARE, SMB_ST_DISK) != 0)
		exit(1);
	if (smb_ctx_readrc(ctx) != 0)
		exit(1);
	if (smb_rc)
		rc_close(smb_rc);

	while ((opt = getopt(argc, argv, STDPARAM_OPT"c:d:f:g:l:n:o:u:w:")) != -1) {
		switch (opt) {
		    case STDPARAM_ARGS:
			error = smb_ctx_opt(ctx, opt, optarg);
			if (error)
				exit(1);
			break;
		    case 'u': {
			struct passwd *pwd;

			pwd = isdigit(optarg[0]) ?
			    getpwuid(atoi(optarg)) : getpwnam(optarg);
			if (pwd == NULL)
				errx(EX_NOUSER, "unknown user '%s'", optarg);
			uid = pwd->pw_uid;
			break;
		    }
		    case 'g': {
			struct group *grp;

			grp = isdigit(optarg[0]) ?
			    getgrgid(atoi(optarg)) : getgrnam(optarg);
			if (grp == NULL)
				errx(EX_NOUSER, "unknown group '%s'", optarg);
			gid = grp->gr_gid;
			break;
		    }
		    case 'd':
			errno = 0;
			dir_mode = strtol(optarg, &next, 8);
			if (errno || *next != 0)
				errx(EX_DATAERR, "invalid value for directory mode");
			break;
		    case 'f':
			errno = 0;
			file_mode = strtol(optarg, &next, 8);
			if (errno || *next != 0)
				errx(EX_DATAERR, "invalid value for file mode");
			break;
		    case '?':
			usage();
			/*NOTREACHED*/
		    case 'n': {
			char *inp, *nsp;

			nsp = inp = optarg;
			while ((nsp = strsep(&inp, ",;:")) != NULL) {
				if (strcasecmp(nsp, "LONG") == 0) {
					build_iovec(&iov, &iovlen,
					    "nolong", NULL, 0);
				} else {
					errx(EX_DATAERR,
					    "unknown suboption '%s'", nsp);
				}
			}
			break;
		    };
		    case 'o':
			getmntopts(optarg, mopts, &mntflags, 0);
			p = strchr(optarg, '=');
			val = NULL;
			if (p != NULL) {
				*p = '\0';
				val = p + 1;
			}
			build_iovec(&iov, &iovlen, optarg, val, (size_t)-1);
			break;
		    case 'c':
			switch (optarg[0]) {
			    case 'l':
				caseopt |= SMB_CS_LOWER;
				break;
			    case 'u':
				caseopt |= SMB_CS_UPPER;
				break;
			    default:
		    		errx(EX_DATAERR, "invalid suboption '%c' for -c",
				    optarg[0]);
			}
			break;
		    default:
			usage();
		}
	}

	if (optind == argc - 2)
		optind++;
	
	if (optind != argc - 1)
		usage();
	realpath(argv[optind], mount_point);

	if (stat(mount_point, &st) == -1)
		err(EX_OSERR, "could not find mount point %s", mount_point);
	if (!S_ISDIR(st.st_mode)) {
		errno = ENOTDIR;
		err(EX_OSERR, "can't mount on %s", mount_point);
	}
/*
	if (smb_getextattr(mount_point, &einfo) == 0)
		errx(EX_OSERR, "can't mount on %s twice", mount_point);
*/
	if (uid == (uid_t)-1)
		uid = st.st_uid;
	if (gid == (gid_t)-1)
		gid = st.st_gid;
	if (file_mode == 0 )
		file_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
	if (dir_mode == 0) {
		dir_mode = file_mode;
		if (dir_mode & S_IRUSR)
			dir_mode |= S_IXUSR;
		if (dir_mode & S_IRGRP)
			dir_mode |= S_IXGRP;
		if (dir_mode & S_IROTH)
			dir_mode |= S_IXOTH;
	}
	/*
	 * For now, let connection be private for this mount
	 */
	ctx->ct_ssn.ioc_opt |= SMBVOPT_PRIVATE;
	ctx->ct_ssn.ioc_owner = ctx->ct_sh.ioc_owner = 0; /* root */
	ctx->ct_ssn.ioc_group = ctx->ct_sh.ioc_group = gid;
	opt = 0;
	if (dir_mode & S_IXGRP)
		opt |= SMBM_EXECGRP;
	if (dir_mode & S_IXOTH)
		opt |= SMBM_EXECOTH;
	ctx->ct_ssn.ioc_rights |= opt;
	ctx->ct_sh.ioc_rights |= opt;
	error = smb_ctx_resolve(ctx);
	if (error)
		exit(1);
	error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE);
	if (error) {
		exit(1);
	}

	fd = ctx->ct_fd;

	build_iovec(&iov, &iovlen, "fstype", strdup("smbfs"), -1);
	build_iovec(&iov, &iovlen, "fspath", mount_point, -1);
	build_iovec_argf(&iov, &iovlen, "fd", "%d", fd);
	build_iovec(&iov, &iovlen, "mountpoint", mount_point, -1);
	build_iovec_argf(&iov, &iovlen, "uid", "%d", uid);
	build_iovec_argf(&iov, &iovlen, "gid", "%d", gid);
	build_iovec_argf(&iov, &iovlen, "file_mode", "%d", file_mode);
	build_iovec_argf(&iov, &iovlen, "dir_mode", "%d", dir_mode);
	build_iovec_argf(&iov, &iovlen, "caseopt", "%d", caseopt);
	build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof errmsg); 

	error = nmount(iov, iovlen, mntflags);
	smb_ctx_done(ctx);
	if (error) {
		smb_error("mount error: %s %s", error, mount_point, errmsg);
		exit(1);
	}
	return 0;
}
Exemplo n.º 5
0
static int
mount_struct(_Bool verbose, struct mount_data_s *mntdp)
{
	fsu_fs_t *fs;
	int rv;

	fs = mntdp->mntd_fs;

	/*
	 * Switch the default process to the native syscalls.
	 * The bad thing about this is that it will fail in unobvious
	 * way if programs using this go multithreaded, but worry about
	 * that if it happens.
	 */
	rump_i_know_what_i_am_doing_with_sysents = 1;
	rump_pub_lwproc_sysent_usenative();

	rv = fs->fs_parseargs(mntdp->mntd_argc, mntdp->mntd_argv, fs->fs_args,
	    &(mntdp->mntd_flags), mntdp->mntd_canon_dev, mntdp->mntd_canon_dir);
	if (rv != 0)
		return -1;

	if (rump_sys_mkdir(MOUNT_DIRECTORY, 0777) == -1 && errno != EEXIST)
		err(-1, "mkdir");
	strcpy(mntdp->mntd_canon_dir, MOUNT_DIRECTORY);

	rv = fsu_load_fs(fs->fs_name);

	if (rv == 0) {
		rv = rump_sys_mount(fs->fs_name, mntdp->mntd_canon_dir,
		    mntdp->mntd_flags, fs->fs_args, fs->fs_args_size);
#if 0
		/*
		 * This will result in a lot of spam for fs type autodetection,
		 * so need to come up with a better scheme here.
		 */
		if (rv == -1)
			warn("mount failed");
#endif
	}

	if (rv == 0) {
		/* fork a rump kernel process to chroot() to the mountpoint */
		if ((rv = rump_pub_lwproc_rfork(RUMP_RFCFDG)) != 0) {
			warnx("fork failed!");
			rump_sys_unmount(MOUNT_DIRECTORY, 0);
		} else {
			atexit(fsu_unmount);
			rump_sys_chroot(MOUNT_DIRECTORY);
		}
	}
#ifdef WITH_SMBFS
	if (strcmp(fs->fs_name, MOUNT_SMBFS) == 0) {
		extern struct smb_ctx sctx;

		smb_ctx_done(&sctx);
	}
#endif
	if (rv != 0 && verbose) {
		warn(NULL);
		fprintf(stderr, "%s is not a valid %s image\n",
		    mntdp->mntd_fsdevice, fs->fs_name);
	}

	return rv;
}