/* * smbrdr_logon * * I'm not sure this really needs to do anything, but for now * let's go ahead and authenticate here so this can return a * status reflecting the outcome of authentication. * * If this successfully builds an smb_ctx, it just frees it. * The driver retains sessions for a little while after the * last reference goes away, so the session created here will * usually still exist when the next call to smbrdr_ctx_new * asks for this server+user (immediately after this returns), * and only one session setup will go over the wire. */ int smbrdr_logon(char *srv, char *dom, char *user) { struct smb_ctx *ctx; int err; err = smbrdr_ctx_new(&ctx, srv, dom, user); if (err == 0) smb_ctx_free(ctx); return (err); }
/* * Try making a connection with the server described by * the info in the smb_iod_ssn_t arg. If successful, * start an IOD thread to service it, then return to * the client side of the door. */ int iod_newvc(smb_iod_ssn_t *clnt_ssn) { smb_ctx_t *ctx; thread_t tid; int err; /* * This needs to essentially "clone" the smb_ctx_t * from the client side of the door, or at least * as much of it as we need while creating a VC. */ err = smb_ctx_alloc(&ctx); if (err) return (err); bcopy(clnt_ssn, &ctx->ct_iod_ssn, sizeof (ctx->ct_iod_ssn)); /* * Do the initial connection setup here, so we can * report the outcome to the door client. */ err = smb_iod_connect(ctx); if (err != 0) goto out; /* * Create the driver session now, so we don't * race with the door client findvc call. */ if ((err = smb_ctx_gethandle(ctx)) != 0) goto out; if (ioctl(ctx->ct_dev_fd, SMBIOC_SSN_CREATE, &ctx->ct_ssn) < 0) { err = errno; goto out; } /* The rest happens in the iod_work thread. */ err = thr_create(NULL, 0, iod_work, ctx, THR_DETACHED, &tid); if (err == 0) { /* * Given to the new thread. * free at end of iod_work */ ctx = NULL; } out: if (ctx) smb_ctx_free(ctx); return (err); }
/* * Be the reader thread for some VC. * * This is started by a door call thread, which means * this is always at least the 2nd thread, therefore * it should never see thr_count==0 or terminating. */ void * iod_work(void *arg) { smb_ctx_t *ctx = arg; mutex_lock(&iod_mutex); if (iod_thr_count++ == 0) { alarm(0); DPRINT("iod_work: cancelled alarm\n"); } mutex_unlock(&iod_mutex); (void) smb_iod_work(ctx); mutex_lock(&iod_mutex); if (--iod_thr_count == 0) { DPRINT("iod_work: schedule alarm\n"); alarm(ALARM_TIME); } mutex_unlock(&iod_mutex); smb_ctx_free(ctx); return (NULL); }
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); }
void smbrdr_ctx_free(struct smb_ctx *ctx) { smb_ctx_free(ctx); }
/* * 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 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); }