int cmd_view(int argc, char *argv[]) { struct smb_ctx sctx, *ctx = &sctx; struct smb_share_info_1 *rpbuf, *ep; char *cp; u_int16_t type; int error, opt, bufsize, i, entries, total; if (argc < 2) view_usage(); if (smb_ctx_init(ctx, argc, argv, SMBL_VC, SMBL_VC, SMB_ST_ANY) != 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)) != EOF) { switch(opt){ case STDPARAM_ARGS: error = smb_ctx_opt(ctx, opt, optarg); if (error) exit(1); break; default: view_usage(); /*NOTREACHED*/ } } #ifdef APPLE if (loadsmbvfs()) errx(EX_OSERR, "SMB filesystem is not available"); #endif smb_ctx_setshare(ctx, "IPC$", SMB_ST_ANY); if (smb_ctx_resolve(ctx) != 0) exit(1); error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE); if (error) { smb_error("could not login to server %s", error, ctx->ct_ssn.ioc_srvname); exit(1); } printf("Share Type Comment\n"); printf("-------------------------------\n"); bufsize = 0xffe0; /* samba notes win2k bug with 65535 */ rpbuf = malloc(bufsize); error = smb_rap_NetShareEnum(ctx, 1, rpbuf, bufsize, &entries, &total); if (error && error != (SMB_ERROR_MORE_DATA | SMB_RAP_ERROR)) { smb_error("unable to list resources", error); exit(1); } for (ep = rpbuf, i = 0; i < entries; i++, ep++) { type = letohs(ep->shi1_type); cp = (char*)rpbuf + ep->shi1_remark; printf("%-12s %-10s %s\n", ep->shi1_netname, shtype[min(type, sizeof shtype / sizeof(char *) - 1)], ep->shi1_remark ? nls_str_toloc(cp, cp) : ""); } printf("\n%d shares listed from %d available\n", entries, total); free(rpbuf); return 0; }
int cmd_discon(int argc, char *argv[]) { struct smb_ctx *ctx; int error, opt; if (argc < 2) discon_usage(); error = smb_ctx_alloc(&ctx); if (error != 0) return (error); error = smb_ctx_scan_argv(ctx, argc, argv, SMBL_SERVER, SMBL_SERVER, USE_WILDCARD); if (error != 0) goto out; error = smb_ctx_readrc(ctx); if (error != 0) goto out; while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) { if (opt == '?') discon_usage(); error = smb_ctx_opt(ctx, opt, optarg); if (error != 0) goto out; } /* * Resolve the server address, * setup derived defaults. */ error = smb_ctx_resolve(ctx); if (error != 0) goto out; /* * Have server, user, etc. from above: * smb_ctx_scan_argv, option settings. * * Lookup a session without creating. * (First part of smb_ctx_get_ssn) * If we find the session, kill it. */ error = smb_ctx_findvc(ctx); if (error == ENOENT) { /* Already gone. We're done. */ if (smb_debug) fprintf(stderr, "session not found\n"); error = 0; goto out; } if (error == 0) { /* Found session. Kill it. */ error = smb_ctx_kill(ctx); } if (error != 0) { smb_error(gettext("//%s: discon failed"), error, ctx->ct_fullserver); } out: smb_ctx_free(ctx); return (error); }
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; }
/* * Setup a new SMB client context. * * Get the SMB server's configuration stuff and * store it in the new client context object. */ int smbrdr_ctx_new(struct smb_ctx **ctx_p, char *server, char *domain, char *user) { struct smb_ctx *ctx = NULL; uchar_t nthash[SMBAUTH_HASH_SZ]; int64_t lmcl; int authflags, err; assert(server != NULL); assert(domain != NULL); assert(user != NULL); if ((err = smb_ctx_alloc(&ctx)) != 0) return (NT_STATUS_NO_MEMORY); /* * Set server, share, domain, user * (in the ctx handle). */ (void) smb_ctx_setfullserver(ctx, server); (void) smb_ctx_setshare(ctx, "IPC$", USE_IPC); (void) smb_ctx_setdomain(ctx, domain, B_TRUE); (void) smb_ctx_setuser(ctx, user, B_TRUE); /* * Set auth. info (hash) and type. */ if (user[0] == '\0') { authflags = SMB_AT_ANON; } else { (void) smb_config_getnum(SMB_CI_LM_LEVEL, &lmcl); if (lmcl <= 2) { /* Send NTLM */ authflags = SMB_AT_NTLM1; } else { /* Send NTLMv2 */ authflags = SMB_AT_NTLM2; } smb_ipc_get_passwd(nthash, sizeof (nthash)); (void) smb_ctx_setpwhash(ctx, nthash, NULL); } (void) smb_ctx_setauthflags(ctx, authflags); /* * Do lookup, connect, session setup, tree connect. * Or find and reuse a session/tree, if one exists. */ if ((err = smb_ctx_resolve(ctx)) != 0) { err = NT_STATUS_BAD_NETWORK_PATH; goto errout; } if ((err = smb_ctx_get_ssn(ctx)) != 0) { err = NT_STATUS_NETWORK_ACCESS_DENIED; goto errout; } if ((err = smb_ctx_get_tree(ctx)) != 0) { err = NT_STATUS_BAD_NETWORK_NAME; goto errout; } /* Success! */ *ctx_p = ctx; return (0); errout: smb_ctx_free(ctx); return (err); }
int cmd_view(int argc, char *argv[]) { struct smb_ctx *ctx; int error, err2, opt; if (argc < 2) view_usage(); error = smb_ctx_alloc(&ctx); if (error) return (error); error = smb_ctx_scan_argv(ctx, argc, argv, SMBL_SERVER, SMBL_SERVER, USE_WILDCARD); if (error) return (error); error = smb_ctx_readrc(ctx); if (error) return (error); while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) { if (opt == '?') view_usage(); error = smb_ctx_opt(ctx, opt, optarg); if (error) return (error); } smb_ctx_setshare(ctx, "IPC$", USE_IPC); /* * Resolve the server address, * setup derived defaults. */ error = smb_ctx_resolve(ctx); if (error) return (error); /* * Have server, share, etc. from above: * smb_ctx_scan_argv, option settings. * Get the session and tree. */ again: error = smb_ctx_get_ssn(ctx); if (error == EAUTH) { err2 = smb_get_authentication(ctx); if (err2 == 0) goto again; } if (error) { smb_error(gettext("//%s: login failed"), error, ctx->ct_fullserver); return (error); } error = smb_ctx_get_tree(ctx); if (error) { smb_error(gettext("//%s/%s: tree connect failed"), error, ctx->ct_fullserver, ctx->ct_origshare); return (error); } /* * Have IPC$ tcon, now list shares. * This prints its own errors. */ error = enum_shares(ctx); if (error) return (error); smb_ctx_free(ctx); return (0); }
int smb_ctx_lookup(struct smb_ctx *ctx, int level, int flags) { struct smbioc_lookup rq; int error; if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) { smb_error("smb_ctx_lookup() data is not resolved", 0); return EINVAL; } if (ctx->ct_fd != -1) { smb_kops.ko_close(ctx->ct_fd); ctx->ct_fd = -1; } error = smb_ctx_gethandle(ctx); if (error) { smb_error("can't get handle to requester (no /dev/"NSMB_NAME"* device available)", 0); return EINVAL; } bzero(&rq, sizeof(rq)); bcopy(&ctx->ct_ssn, &rq.ioc_ssn, sizeof(struct smbioc_ossn)); bcopy(&ctx->ct_sh, &rq.ioc_sh, sizeof(struct smbioc_oshare)); rq.ioc_flags = flags; rq.ioc_level = level; if (smb_kops.ko_ioctl(ctx->ct_fd, SMBIOC_LOOKUP, &rq) == -1) { error = errno; smb_kops.ko_close(ctx->ct_fd); ctx->ct_fd = -1; /* * Fallback to *SMBSERVER as NetBIOS name. At least * Windows NT and Windows XP require this (or valid * NetBIOS server name), otherwise they refuse connection. */ if (smb_ctx_setserver(ctx, "*SMBSERVER") != 0) goto fail; error = smb_ctx_resolve(ctx); if (error) goto fail; error = smb_ctx_gethandle(ctx); if (error) goto fail; bcopy(&ctx->ct_ssn, &rq.ioc_ssn, sizeof(struct smbioc_ossn)); if (smb_kops.ko_ioctl(ctx->ct_fd, SMBIOC_LOOKUP, &rq) != -1) goto success; error = errno; fail: if (flags & SMBLK_CREATE) smb_error("unable to open connection", error); return error; } success: return 0; }
int cmd_print(int argc, char *argv[]) { struct smb_ctx sctx, *ctx = &sctx; smbfh fh; off_t offset; char buf[8192]; char *filename; char fnamebuf[256]; int error, opt, i, file, count; if (argc < 2) view_usage(); if (smb_ctx_init(ctx, argc, argv, SMBL_SHARE, SMBL_SHARE, SMB_ST_PRINTER) != 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)) != EOF) { switch(opt){ case STDPARAM_ARGS: error = smb_ctx_opt(ctx, opt, optarg); if (error) exit(1); break; default: view_usage(); /*NOTREACHED*/ } } if (optind + 1 >= argc) print_usage(); filename = argv[optind + 1]; if (strcmp(filename, "-") == 0) { file = 0; /* stdin */ filename = "stdin"; } else { file = open(filename, O_RDONLY, 0); if (file < 0) { smb_error("could not open file %s\n", errno, filename); exit(1); } } if (smb_ctx_resolve(ctx) != 0) exit(1); error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE); if (error) { smb_error("could not login to server %s", error, ctx->ct_ssn.ioc_srvname); exit(1); } snprintf(fnamebuf, sizeof(fnamebuf), "%s_%s_%s", ctx->ct_ssn.ioc_user, ctx->ct_ssn.ioc_srvname, filename); error = smb_smb_open_print_file(ctx, 0, 1, fnamebuf, &fh); if (error) { smb_error("could not open print job", error); exit(1); } offset = 0; error = 0; for(;;) { count = read(file, buf, sizeof(buf)); if (count == 0) break; if (count < 0) { error = errno; smb_error("error reading input file\n", error); break; } i = smb_write(ctx, fh, offset, count, buf); if (i < 0) { error = errno; smb_error("error writing spool file\n", error); break; } if (i != count) { smb_error("incomplete write to spool file\n", 0); error = EIO; break; } offset += count; } close(file); error = smb_smb_close_print_file(ctx, fh); if (error) smb_error("an error while closing spool file\n", error); return error ? 1 : 0; }
int cmd_print(int argc, char *argv[]) { struct smb_ctx *ctx = NULL; char *filename; int error, opt; int file = -1; /* last arg is the print file. */ if (argc < 3) print_usage(); error = smb_ctx_alloc(&ctx); if (error) goto out; error = smb_ctx_scan_argv(ctx, argc-1, argv, SMBL_SHARE, SMBL_SHARE, USE_SPOOLDEV); if (error) goto out; error = smb_ctx_readrc(ctx); if (error) goto out; while ((opt = getopt(argc-1, argv, STDPARAM_OPT)) != EOF) { if (opt == '?') print_usage(); error = smb_ctx_opt(ctx, opt, optarg); if (error) goto out; } if (optind != argc-2) print_usage(); filename = argv[argc-1]; if (strcmp(filename, "-") == 0) { file = 0; /* stdin */ filename = "stdin"; } else { file = open(filename, O_RDONLY, 0); if (file < 0) { smb_error("could not open file %s\n", errno, filename); exit(1); } } /* * Resolve the server address, * setup derived defaults. */ error = smb_ctx_resolve(ctx); if (error) goto out; /* * Have server + share names, options etc. * Get the session and tree. */ again: error = smb_ctx_get_ssn(ctx); if (error == EAUTH) { int err2 = smb_get_authentication(ctx); if (err2 == 0) goto again; } if (error) { smb_error(gettext("//%s: login failed"), error, ctx->ct_fullserver); goto out; } error = smb_ctx_get_tree(ctx); if (error) { smb_error(gettext("//%s/%s: tree connect failed"), error, ctx->ct_fullserver, ctx->ct_origshare); goto out; } /* * Have the printer share connection. * Print the file. */ snprintf(titlebuf, sizeof (titlebuf), "%s %s", ctx->ct_user, filename); error = print_file(ctx, titlebuf, file); out: /* don't close stdin (file=0) */ if (file > 0) close(file); smb_ctx_free(ctx); return (error); }