Ejemplo n.º 1
0
int
smb_ctx_login(struct smb_ctx *ctx)
{
	struct smbioc_ossn *ssn = &ctx->ct_ssn;
	struct smbioc_oshare *sh = &ctx->ct_sh;
	int error;

	if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) {
		smb_error("smb_ctx_resolve() should be called first", 0);
		return EINVAL;
	}
	if (ctx->ct_fd != -1) {
		close(ctx->ct_fd);
		ctx->ct_fd = -1;
	}
	error = smb_ctx_gethandle(ctx);
	if (error) {
		smb_error("can't get handle to requester", 0);
		return EINVAL;
	}
	if (ioctl(ctx->ct_fd, SMBIOC_OPENSESSION, ssn) == -1) {
		error = errno;
		smb_error("can't open session to server %s", error, ssn->ioc_srvname);
		return error;
	}
	if (sh->ioc_share[0] == 0)
		return 0;
	if (ioctl(ctx->ct_fd, SMBIOC_OPENSHARE, sh) == -1) {
		error = errno;
		smb_error("can't connect to share //%s/%s", error,
		    ssn->ioc_srvname, sh->ioc_share);
		return error;
	}
	return 0;
}
Ejemplo n.º 2
0
int
smb_ctx_setcharset(struct smb_ctx *ctx, const char *arg)
{
	char *cp, *servercs, *localcs;
	int cslen = sizeof(ctx->ct_ssn.ioc_localcs);
	int scslen, lcslen, error;

	cp = strchr(arg, ':');
	lcslen = cp ? (cp - arg) : 0;
	if (lcslen == 0 || lcslen >= cslen) {
		smb_error("invalid local charset specification (%s)", 0, arg);
		return EINVAL;
	}
	scslen = (size_t)strlen(++cp);
	if (scslen == 0 || scslen >= cslen) {
		smb_error("invalid server charset specification (%s)", 0, arg);
		return EINVAL;
	}
	localcs = memcpy(ctx->ct_ssn.ioc_localcs, arg, lcslen);
	localcs[lcslen] = 0;
	servercs = strcpy(ctx->ct_ssn.ioc_servercs, cp);
	error = nls_setrecode(localcs, servercs);
	if (error == 0)
		return 0;
	smb_error("can't initialize iconv support (%s:%s)",
	    error, localcs, servercs);
	localcs[0] = 0;
	servercs[0] = 0;
	return error;
}
Ejemplo n.º 3
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) {
		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)", 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 (ioctl(ctx->ct_fd, SMBIOC_LOOKUP, &rq) == -1) {
		error = errno;
		if (flags & SMBLK_CREATE)
			smb_error("unable to open connection", error);
		return error;
	}
	return 0;
}
Ejemplo n.º 4
0
static int
smb_parse_owner(char *pair, uid_t *uid, gid_t *gid)
{
	struct group *gr;
	struct passwd *pw;
	char *cp;

	cp = strchr(pair, ':');
	if (cp) {
		*cp++ = '\0';
		if (*cp) {
			gr = getgrnam(cp);
			if (gr) {
				*gid = gr->gr_gid;
			} else
				smb_error("Invalid group name %s, ignored",
				    0, cp);
		}
	}
	if (*pair) {
		pw = getpwnam(pair);
		if (pw) {
			*uid = pw->pw_uid;
		} else
			smb_error("Invalid user name %s, ignored", 0, pair);
	}
	endpwent();
	return 0;
}
Ejemplo n.º 5
0
int
nb_ctx_resolve(struct nb_ctx *ctx)
{
	struct sockaddr *sap;
	int error;

	ctx->nb_flags &= ~NBCF_RESOLVED;

	if (ctx->nb_nsname == NULL) {
		ctx->nb_ns.sin_addr.s_addr = htonl(INADDR_BROADCAST);
	} else {
		error = nb_resolvehost_in(ctx->nb_nsname, &sap);
		if (error) {
			smb_error("can't resolve %s", error, ctx->nb_nsname);
			return error;
		}
		if (sap->sa_family != AF_INET) {
			smb_error("unsupported address family %d", 0,
			    sap->sa_family);
			free(sap);
			return EINVAL;
		}
		bcopy(sap, &ctx->nb_ns, sizeof(ctx->nb_ns));
		free(sap);
	}
	ctx->nb_ns.sin_port = htons(137);
	ctx->nb_ns.sin_family = AF_INET;
	ctx->nb_ns.sin_len = sizeof(ctx->nb_ns);
	ctx->nb_flags |= NBCF_RESOLVED;
	return 0;
}
Ejemplo n.º 6
0
Archivo: ctx.c Proyecto: execunix/vinos
int
smb_ctx_setserver(struct smb_ctx *ctx, const char *name)
{
	char *d;

	/*
	 * If the name contains dot, it's likely a IP address
	 * or a name. Update srvaddr in that case, and use
	 * first part of the name (up to the dot) as NetBIOS name.
	 */
	if ((d = strchr(name, '.'))) {
		static char nm[sizeof(ctx->ct_ssn.ioc_srvname)];
		int error;

		error = smb_ctx_setsrvaddr(ctx, name);
		if (error)
			return (error);
		
		/* cut name to MAXSRVNAMELEN */
		if (strlen(name) >= sizeof(ctx->ct_ssn.ioc_srvname)) {
			snprintf(nm, sizeof(nm), "%.*s",
			    (int)(sizeof(ctx->ct_ssn.ioc_srvname) - 1), name);
			name = nm;
		}
	}

	if (strlen(name) >= sizeof(ctx->ct_ssn.ioc_srvname)) {
		smb_error("server name '%s' too long", 0, name);
		return ENAMETOOLONG;
	}
	nls_str_upper(ctx->ct_ssn.ioc_srvname, name);
	return 0;
}
Ejemplo n.º 7
0
Archivo: rq.c Proyecto: coyizumi/cs111
void
smb_rq_wend(struct smb_rq *rqp)
{
	if (rqp->rq_rq.mb_count & 1)
		smb_error("smbrq_wend: odd word count\n", 0);
	rqp->rq_wcount = rqp->rq_rq.mb_count / 2;
	rqp->rq_rq.mb_count = 0;
}
Ejemplo n.º 8
0
static int
print_file(smb_ctx_t *ctx, char *title, int file)
{
	off_t offset;
	int rcnt, wcnt;
	int setup_len = 0;		/* No printer setup data */
	int mode = MODE_GRAPHICS;	/* treat as raw data */
	int error = 0;
	int pfd = -1;

	pfd = smb_open_printer(ctx, title, setup_len, mode);
	if (pfd < 0) {
		error = errno;
		smb_error("could not open print job", error);
		return (error);
	}

	offset = 0;
	for (;;) {
		rcnt = read(file, databuf, sizeof (databuf));
		if (rcnt < 0) {
			error = errno;
			smb_error("error reading input file\n", error);
			break;
		}
		if (rcnt == 0)
			break;

		wcnt = smb_fh_write(pfd, offset, rcnt, databuf);
		if (wcnt < 0) {
			error = errno;
			smb_error("error writing spool file\n", error);
			break;
		}
		if (wcnt != rcnt) {
			smb_error("incomplete write to spool file\n", 0);
			error = EIO;
			break;
		}
		offset += wcnt;
	}

	(void) smb_fh_close(pfd);
	return (error);
}
Ejemplo n.º 9
0
int
cmd_lookup(int argc, char *argv[])
{
    struct nb_ctx *ctx;
    struct sockaddr *sap;
    char *hostname;
    int error, opt;

    if (argc < 2)
        lookup_usage();
    error = nb_ctx_create(&ctx);
    if (error) {
        smb_error("unable to create nbcontext", error);
        exit(1);
    }
    if (smb_open_rcfile() == 0) {
        if (nb_ctx_readrcsection(smb_rc, ctx, "default", 0) != 0)
            exit(1);
        rc_close(smb_rc);
    }
    while ((opt = getopt(argc, argv, "w:")) != EOF) {
        switch(opt) {
        case 'w':
            nb_ctx_setns(ctx, optarg);
            break;
        default:
            lookup_usage();
            /*NOTREACHED*/
        }
    }
    if (optind >= argc)
        lookup_usage();
    if (nb_ctx_resolve(ctx) != 0)
        exit(1);
    hostname = argv[argc - 1];
    /*	printf("Looking for %s...\n", hostname);*/
    error = nbns_resolvename(hostname, ctx, &sap);
    if (error) {
        smb_error("unable to resolve %s", error, hostname);
        exit(1);
    }
    printf("Got response from %s\n", inet_ntoa(ctx->nb_lastns.sin_addr));
    printf("IP address of %s: %s\n", hostname, inet_ntoa(((struct sockaddr_in*)sap)->sin_addr));
    return 0;
}
Ejemplo n.º 10
0
/*
 * XXX - NLS, or CF?  We should probably use the same routine for all
 * conversions.
 */
char *
convert_wincs_to_utf8(const char *windows_string)
{
#ifdef NOTPORTED
	CFStringRef s;
	CFIndex maxlen;
	char *result;

	s = CFStringCreateWithCString(NULL, windows_string, 
		get_windows_encoding_equivalent());
	if (s == NULL) {
		smb_error("CFStringCreateWithCString for Windows code page failed on \"%s\" ", -1,
		    windows_string);

		/* kCFStringEncodingMacRoman should always succeed */
		s = CFStringCreateWithCString(NULL, windows_string, 
		    kCFStringEncodingMacRoman);
		if (s == NULL) {
			smb_error("CFStringCreateWithCString for Windows code page failed on \"%s\" with kCFStringEncodingMacRoman - skipping",
			    -1, windows_string);
			return NULL;
		}
	}

	maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s),
	    kCFStringEncodingUTF8) + 1;
	result = malloc(maxlen);
	if (result == NULL) {
		smb_error("Couldn't allocate buffer for UTF-8 string for \"%s\" - skipping", -1,
		    windows_string);
		CFRelease(s);
		return NULL;
	}
	if (!CFStringGetCString(s, result, maxlen, kCFStringEncodingUTF8)) {
		smb_error("CFStringGetCString for UTF-8 failed on \"%s\" - skipping",
		    -1, windows_string);
		CFRelease(s);
		return NULL;
	}
	CFRelease(s);
	return result;
#else /* NOTPORTED */
	return (strdup((char*)windows_string));
#endif /* NOTPORTED */
}
Ejemplo n.º 11
0
int
smb_ctx_setserver(struct smb_ctx *ctx, const char *name)
{
	if (strlen(name) >= SMB_MAXSRVNAMELEN) {
		smb_error("server name '%s' too long", 0, name);
		return ENAMETOOLONG;
	}
	nls_str_upper(ctx->ct_ssn.ioc_srvname, name);
	return 0;
}
Ejemplo n.º 12
0
int
smb_ctx_setuser(struct smb_ctx *ctx, const char *name)
{
	if (strlen(name) > SMB_MAXUSERNAMELEN) {
		smb_error("user name '%s' too long", 0, name);
		return ENAMETOOLONG;
	}
	nls_str_upper(ctx->ct_ssn.ioc_user, name);
	return 0;
}
Ejemplo n.º 13
0
int
smb_ctx_setworkgroup(struct smb_ctx *ctx, const char *name)
{
	if (strlen(name) >= SMB_MAXUSERNAMELEN) {
		smb_error("workgroup name '%s' too long", 0, name);
		return ENAMETOOLONG;
	}
	nls_str_upper(ctx->ct_ssn.ioc_workgroup, name);
	return 0;
}
Ejemplo n.º 14
0
static char *
convert_ucs2xx_to_utf8(iconv_t cd, const uint16_t *us)
{
	char *obuf, *optr;
	const char *iptr;
	size_t  ileft, obsize, oleft, ret;

	if (cd == (iconv_t)-1) {
		smb_error(dgettext(TEXT_DOMAIN,
		    "iconv_open(UTF-8/UCS-2)"), -1);
		return (NULL);
	}

	iptr = (const char *)us;
	ileft = unicode_strlen(us);
	ileft *= 2; /* now bytes */

	/* Worst-case output size is 2x input size. */
	oleft = ileft * 2;
	obsize = oleft + 2; /* room for null */
	obuf = malloc(obsize);
	if (!obuf)
		return (NULL);
	optr = obuf;

	ret = iconv(cd, &iptr, &ileft, &optr, &oleft);
	*optr = '\0';
	if (ret == (size_t)-1) {
		smb_error(dgettext(TEXT_DOMAIN,
		    "iconv(%s) failed"), errno, obuf);
	}
	if (ileft) {
		smb_error(dgettext(TEXT_DOMAIN,
		    "iconv(%s) failed"), -1, obuf);
		/*
		 * XXX: What's better?  return NULL?
		 * The truncated string? << for now
		 */
	}

	return (obuf);
}
Ejemplo n.º 15
0
static uint16_t *
convert_utf8_to_ucs2xx(iconv_t cd, const char *utf8_string)
{
	uint16_t *obuf, *optr;
	const char *iptr;
	size_t  ileft, obsize, oleft, ret;

	if (cd == (iconv_t)-1) {
		smb_error(dgettext(TEXT_DOMAIN,
		    "iconv_open(UCS-2/UTF-8)"), -1);
		return (NULL);
	}

	iptr = utf8_string;
	ileft = strlen(iptr);

	/* Worst-case output size is 2x input size. */
	oleft = ileft * 2;
	obsize = oleft + 2; /* room for null */
	obuf = malloc(obsize);
	if (!obuf)
		return (NULL);
	optr = obuf;

	ret = iconv(cd, &iptr, &ileft, (char **)&optr, &oleft);
	*optr = '\0';
	if (ret == (size_t)-1) {
		smb_error(dgettext(TEXT_DOMAIN,
		    "iconv(%s) failed"), errno, utf8_string);
	}
	if (ileft) {
		smb_error(dgettext(TEXT_DOMAIN,
		    "iconv(%s) failed"), -1, utf8_string);
		/*
		 * XXX: What's better?  return NULL?
		 * The truncated string? << for now
		 */
	}

	return (obuf);
}
Ejemplo n.º 16
0
static int
smb_addiconvtbl(const char *to, const char *from, const u_char *tbl)
{
	int error;

	error = kiconv_add_xlat_table(to, from, tbl);
	if (error && error != EEXIST) {
		smb_error("can not setup kernel iconv table (%s:%s)", error,
		    from, to);
		return error;
	}
	return 0;
}
Ejemplo n.º 17
0
int
smb_ctx_setshare(struct smb_ctx *ctx, const char *share, int stype)
{
	if (strlen(share) >= SMB_MAXSHARENAMELEN) {
		smb_error("share name '%s' too long", 0, share);
		return ENAMETOOLONG;
	}
	nls_str_upper(ctx->ct_sh.ioc_share, share);
	if (share[0] != 0)
		ctx->ct_parsedlevel = SMBL_SHARE;
	ctx->ct_sh.ioc_stype = stype;
	return 0;
}
Ejemplo n.º 18
0
/*
 * level values:
 * 0 - default
 * 1 - server
 * 2 - server:user
 * 3 - server:user:share
 */
static int
smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
{
	char *p;
	int error;

	if (level >= 0) {
		rc_getstringptr(smb_rc, sname, "charsets", &p);
		if (p) {
			error = smb_ctx_setcharset(ctx, p);
			if (error)
				smb_error("charset specification in the section '%s' ignored", error, sname);
		}
	}
	if (level <= 1) {
		rc_getint(smb_rc, sname, "timeout", &ctx->ct_ssn.ioc_timeout);
		rc_getint(smb_rc, sname, "retry_count", &ctx->ct_ssn.ioc_retrycount);
	}
	if (level == 1) {
		rc_getstringptr(smb_rc, sname, "addr", &p);
		if (p) {
			error = smb_ctx_setsrvaddr(ctx, p);
			if (error) {
				smb_error("invalid address specified in the section %s", 0, sname);
				return error;
			}
		}
	}
	if (level >= 2) {
		rc_getstringptr(smb_rc, sname, "password", &p);
		if (p)
			smb_ctx_setpassword(ctx, p);
	}
	rc_getstringptr(smb_rc, sname, "workgroup", &p);
	if (p)
		smb_ctx_setworkgroup(ctx, p);
	return 0;
}
Ejemplo n.º 19
0
int
smb_ctx_setpassword(struct smb_ctx *ctx, const char *passwd)
{
	if (passwd == NULL)
		return EINVAL;
	if (strlen(passwd) >= SMB_MAXPASSWORDLEN) {
		smb_error("password too long", 0);
		return ENAMETOOLONG;
	}
	if (strncmp(passwd, "$$1", 3) == 0)
		smb_simpledecrypt(ctx->ct_ssn.ioc_password, passwd);
	else
		strcpy(ctx->ct_ssn.ioc_password, passwd);
	strcpy(ctx->ct_sh.ioc_password, ctx->ct_ssn.ioc_password);
	return 0;
}
Ejemplo n.º 20
0
int
nb_ctx_setscope(struct nb_ctx *ctx, const char *scope)
{
	size_t slen = strlen(scope);

	if (slen >= 128) {
		smb_error("scope '%s' is too long", 0, scope);
		return ENAMETOOLONG;
	}
	if (ctx->nb_scope)
		free(ctx->nb_scope);
	ctx->nb_scope = malloc(slen + 1);
	if (ctx->nb_scope == NULL)
		return ENOMEM;
	nls_str_upper(ctx->nb_scope, scope);
	return 0;
}
Ejemplo n.º 21
0
int
enum_shares(smb_ctx_t *ctx)
{
	struct share_info *share_info;
	int error, entries, total;

	/*
	 * XXX: Later, try RPC first,
	 * then fall back to RAP...
	 */
	error = smb_netshareenum(ctx, &entries, &total, &share_info);
	if (error) {
		smb_error(gettext("unable to list resources"), error);
		return (error);
	}
	print_shares(entries, total, share_info);
	return (0);
}
Ejemplo n.º 22
0
Archivo: smb2.c Proyecto: Efreak/elinks
static void
smb_directory(int dir, struct string *prefix, struct uri *uri)
{
	struct string buf;
	struct directory_entry *entries;

	if (!is_in_state(init_directory_listing(&buf, uri), S_OK)) {
		smb_error(connection_state(S_OUT_OF_MEM));
	}

	fputs("text/html", header_out);
	fclose(header_out);

	entries = get_smb_directory_entries(dir, prefix);
	add_smb_dir_entries(entries, NULL, &buf);
	add_to_string(&buf, "</pre><hr/></body></html>\n");

	fputs(buf.source, data_out);
	done_string(&buf);
	exit(0);
}
Ejemplo n.º 23
0
/*
 * used level values:
 * 0 - default
 * 1 - server
 */
int
nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx,
	const char *sname, int level)
{
	char *p;
	int error;

	if (level > 1)
		return EINVAL;
	rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo);
	rc_getstringptr(rcfile, sname, "nbns", &p);
	if (p) {
		error = nb_ctx_setns(ctx, p);
		if (error) {
			smb_error("invalid address specified in the section %s", 0, sname);
			return error;
		}
	}
	rc_getstringptr(rcfile, sname, "nbscope", &p);
	if (p)
		nb_ctx_setscope(ctx, p);
	return 0;
}
Ejemplo n.º 24
0
Archivo: smb2.c Proyecto: Efreak/elinks
static void
do_smb(struct connection *conn)
{
	struct uri *uri = conn->uri;
	struct auth_entry *auth = find_auth(uri);
	struct string string;
	unsigned char *url;
	int dir;

	if ((uri->userlen && uri->passwordlen) || !auth) {
		url = get_uri_string(uri, URI_BASE);
	} else {
		unsigned char *uri_string = get_uri_string(uri, URI_HOST | URI_PORT | URI_DATA);

		if (!uri_string || !init_string(&string)) {
			smb_error(connection_state(S_OUT_OF_MEM));
		}
		/* Must URI-encode the username and password to avoid
		 * ambiguity if they contain "/:@" characters.
		 * Libsmbclient then decodes them again, and the
		 * server gets them as they were in auth->user and
		 * auth->password, i.e. as the user typed them in the
		 * auth dialog.  This implies that, if the username or
		 * password contains some characters or bytes that the
		 * user cannot directly type, then she cannot enter
		 * them.  If that becomes an actual problem, it should
		 * be fixed in the auth dialog, e.g. by providing a
		 * hexadecimal input mode.  */
		add_to_string(&string, "smb://");
		encode_uri_string(&string, auth->user, -1, 1);
		add_char_to_string(&string, ':');
		encode_uri_string(&string, auth->password, -1, 1);
		add_char_to_string(&string, '@');
		add_to_string(&string, uri_string);
		url = string.source;
	}

	if (!url) {
		smb_error(connection_state(S_OUT_OF_MEM));
	}
	if (smbc_init(smb_auth, 0)) {
		smb_error(connection_state_for_errno(errno));
	};


	dir = smbc_opendir(url);
	if (dir >= 0) {
		struct string prefix;

		init_string(&prefix);
		add_to_string(&prefix, url);
		add_char_to_string(&prefix, '/');
		smb_directory(dir, &prefix, conn->uri);
		done_string(&prefix);
	} else {
		const int errno_from_opendir = errno;
		char buf[READ_SIZE];
		struct stat sb;
		int r, res, fdout;
		int file = smbc_open(url, O_RDONLY, 0);

		if (file < 0) {
			/* If we're opening the list of shares without
			 * proper authentication, then smbc_opendir
			 * fails with EACCES and smbc_open fails with
			 * ENOENT.  In this case, return the EACCES so
			 * that the parent ELinks process will prompt
			 * for credentials.  */
			if (errno == ENOENT && errno_from_opendir == EACCES)
				errno = errno_from_opendir;
			smb_error(connection_state_for_errno(errno));
		}

		res = smbc_fstat(file, &sb);
		if (res) {
			smb_error(connection_state_for_errno(res));
		}
		/* filesize */
		fprintf(header_out, "%" OFF_PRINT_FORMAT,
			(off_print_T) sb.st_size);
		fclose(header_out);

		fdout = fileno(data_out);
		while ((r = smbc_read(file, buf, READ_SIZE)) > 0) {
			if (safe_write(fdout, buf, r) <= 0)
					break;
		}
		smbc_close(file);
		exit(0);
	}
}
Ejemplo n.º 25
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);
}
Ejemplo n.º 26
0
static int
rpc_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
    struct share_info **entries_listp)
{
	char ctx_string[2+16+1];	/* enough for 64-bit pointer, in hex */
	unsigned_char_p_t binding;
	unsigned32 binding_status;
	rpc_binding_handle_t binding_h;
	int error, i, entries;
	char *addrstr, *srvnamestr;
	unsigned short *usrvnamestr;
	unsigned32 level;
	SHARE_ENUM_STRUCT share_info;
	SHARE_INFO_1_CONTAINER share_info_1_container;
	SHARE_INFO_1 *shares, *share;
	unsigned32 total_entries;
	unsigned32 status, free_status;
	struct share_info *entry_list, *elp;
	static EXCEPTION rpc_x_connect_rejected;
	static int exceptions_initialized;

	sprintf(ctx_string, "%p", ctx);
	rpc_string_binding_compose(NULL, "ncacn_np", ctx_string,
	    "srvsvc", NULL, &binding, &binding_status);
	if (binding_status != rpc_s_ok) {
		smb_error(dgettext(TEXT_DOMAIN,
		    "rpc_string_binding_compose failed with %d"),
		    0, binding_status);
		return (EINVAL);
	}
	rpc_binding_from_string_binding(binding, &binding_h, &status);
	rpc_string_free(&binding, (unsigned32 *)&free_status);
	if (binding_status != rpc_s_ok) {
		smb_error(dgettext(TEXT_DOMAIN,
		    "rpc_binding_from_string_binding failed with %d"), 0,
		    binding_status);
		return (EINVAL);
	}
	level = 1;
	share_info.share_union.level = 1;
	share_info.share_union.tagged_union.share1 = &share_info_1_container;
	share_info_1_container.share_count = 0;
	share_info_1_container.shares = NULL;
	/*
	 * Convert the server IP address to a string, and send that as
	 * the "server name" - that's what Windows appears to do, and
	 * that avoids problems with NetBIOS names containing
	 * non-ASCII characters.
	 */
	addrstr = inet_ntoa(ctx->ct_srvinaddr.sin_addr);
	srvnamestr = malloc(strlen(addrstr) + 3);
	if (srvnamestr == NULL) {
		status = errno;
		smb_error(dgettext(TEXT_DOMAIN,
		    "can't allocate string for server address"), status);
		rpc_binding_free(&binding_h, &free_status);
		return (status);
	}
	strcpy(srvnamestr, "\\\\");
	strcat(srvnamestr, addrstr);
	usrvnamestr = convert_utf8_to_leunicode(srvnamestr);
	if (usrvnamestr == NULL) {
		smb_error(dgettext(TEXT_DOMAIN,
		    "can't convert string for server address to Unicode"), 0);
		rpc_binding_free(&binding_h, &free_status);
		free(srvnamestr);
		return (EINVAL);
	}
	if (!exceptions_initialized) {
		EXCEPTION_INIT(rpc_x_connect_rejected);
		exc_set_status(&rpc_x_connect_rejected, rpc_s_connect_rejected);
		exceptions_initialized = 1;
	}
	/* printf("Calling NetrShareEnum.."); XXX */
	TRY
		status = NetrShareEnum(binding_h, usrvnamestr, &level,
		    &share_info, 4294967295U, &total_entries, NULL);
		if (status != 0)
			smb_error(dgettext(TEXT_DOMAIN,
			    "error from NetrShareEnum call: status = 0x%08x"),
			    0, status);
	/*CSTYLED*/
	CATCH (rpc_x_connect_rejected)
		/*
		 * This is what we get if we can't open the pipe.
		 * That's a normal occurrence when we're talking
		 * to a system that (presumably) doesn't support
		 * DCE RPC on the server side, such as Windows 95/98/Me,
		 * so we don't log an error.
		 */
		/*CSTYLED*/
		status = ENOTSUP;
	CATCH_ALL
		/*
		 * XXX - should we handle some exceptions differently,
		 * returning different errors, and try RAP only for
		 * ENOTSUP?
		 */
		smb_error(dgettext(TEXT_DOMAIN,
		    "error from NetrShareEnum call: exception = %u"),
		    0, THIS_CATCH->match.value);
		status = ENOTSUP;
	ENDTRY
	rpc_binding_free(&binding_h, &free_status);
	free(srvnamestr);
	free(usrvnamestr);
	if (status != 0)
		return (ENOTSUP);

	/*
	 * XXX - if the IDL is correct, it's not clear whether the
	 * unmarshalling code will properly handle the case where
	 * a packet where "share_count" and the max count for the
	 * array of shares don't match; a valid DCE RPC implementation
	 * won't marshal something like that, but there's no guarantee
	 * that the server we're talking to has a valid implementation
	 * (which could be a *malicious* implementation!).
	 */
	entries = share_info.share_union.tagged_union.share1->share_count;
	shares = share_info.share_union.tagged_union.share1->shares;
	entry_list = calloc(entries, sizeof (struct share_info));
	if (entry_list == NULL) {
		error = errno;
		goto cleanup_and_return;
	}
	for (share = shares, elp = entry_list, i = 0; i < entries;
	    i++, share++) {
		elp->type = share->shi1_type;
		elp->netname = convert_unicode_to_utf8(share->shi1_share);
		if (elp->netname == NULL)
			goto fail;
		elp->remark = convert_unicode_to_utf8(share->shi1_remark);
		if (elp->remark == NULL)
			goto fail;
		elp++;
	}
	*entriesp = entries;
	*totalp = total_entries;
	*entries_listp = entry_list;
	error = 0;
	goto cleanup_and_return;

fail:
	error = errno;
	for (elp = entry_list, i = 0; i < entries; i++, elp++) {
		/*
		 * elp->netname is set before elp->remark, so if
		 * elp->netname is null, elp->remark is also null.
		 * If either of them is null, we haven't done anything
		 * to any entries after this one.
		 */
		if (elp->netname == NULL)
			break;
		free(elp->netname);
		if (elp->remark == NULL)
			break;
		free(elp->remark);
	}
	free(entry_list);

cleanup_and_return:
	for (share = shares, i = 0; i < entries; i++, share++) {
		free(share->shi1_share);
		free(share->shi1_remark);
	}
	free(shares);
	/*
	 * XXX - "share1" should be a unique pointer, but we haven't
	 * changed the marshalling code to support non-full pointers
	 * in unions, so we leave it as a full pointer.
	 *
	 * That means that this might, or might not, be changed from
	 * pointing to "share_info_1_container" to pointing to a
	 * mallocated structure, according to the DCE RPC 1.1 IDL spec;
	 * we free it only if it's changed.
	 */
	if (share_info.share_union.tagged_union.share1 !=
	    &share_info_1_container)
		free(share_info.share_union.tagged_union.share1);
	return (error);
}
Ejemplo n.º 27
0
int
smb_rap_request(struct smb_rap *rap, struct smb_ctx *ctx)
{
	u_int16_t *rp, conv;
	u_int32_t *p32;
	char *dp, *p = rap->r_nparam;
	char ptype;
	int error, rdatacnt, rparamcnt, entries, done, dlen;

	rdatacnt = rap->r_rcvbuflen;
	rparamcnt = rap->r_plen;
	error = smb_t2_request(ctx, 0, 0, "\\PIPE\\LANMAN",
	    rap->r_plen, rap->r_pbuf,		/* int tparamcnt, void *tparam */
	    0, NULL,				/* int tdatacnt, void *tdata */
	    &rparamcnt, rap->r_pbuf,		/* rparamcnt, void *rparam */
	    &rdatacnt, rap->r_rcvbuf		/* int *rdatacnt, void *rdata */
	);
	if (error)
		return error;
	rp = (u_int16_t*)rap->r_pbuf;
	rap->r_result = le16toh(*rp++);
	conv = le16toh(*rp++);
	rap->r_npbuf = (char*)rp;
	rap->r_entries = entries = 0;
	done = 0;
	while (!done && *p) {
		ptype = *p;
		switch (ptype) {
		    case 'e':
			rap->r_entries = entries = le16toh(*(u_int16_t*)rap->r_npbuf);
			rap->r_npbuf += 2;
			p++;
			break;
		    default:
			done = 1;
		}
/*		error = smb_rap_parserpparam(p, &p, &plen);
		if (error) {
			smb_error("reply parameter mismath %s", 0, p);
			return EBADRPC;
		}*/
	}
	rap->r_nparam = p;
	/*
	 * In general, unpacking entries we may need to relocate
	 * entries for proper alingning. For now use them as is.
	 */
	dp = rap->r_rcvbuf;
	while (entries--) {
		p = rap->r_sdata;
		while (*p) {
			ptype = *p;
			error = smb_rap_parserpdata(p, &p, &dlen);
			if (error) {
				smb_error("reply data mismath %s", 0, p);
				return EBADRPC;
			}
			switch (ptype) {
			    case 'z':
				p32 = (u_int32_t*)dp;
				*p32 = (*p32 & 0xffff) - conv;
				break;
			}
			dp += dlen;
		}
	}
	return error;
}
Ejemplo n.º 28
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;
}
Ejemplo n.º 29
0
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;
}
Ejemplo n.º 30
0
/*
 * Verify context before connect operation(s),
 * lookup specified server and try to fill all forgotten fields.
 */
int
smb_ctx_resolve(struct smb_ctx *ctx)
{
	struct smbioc_ossn *ssn = &ctx->ct_ssn;
	struct smbioc_oshare *sh = &ctx->ct_sh;
	struct nb_name nn;
	struct sockaddr *sap;
	struct sockaddr_nb *salocal, *saserver;
	char *cp;
	u_char cstbl[256];
	u_int i;
	int error = 0;
	
	ctx->ct_flags &= ~SMBCF_RESOLVED;
	if (ssn->ioc_srvname[0] == 0) {
		smb_error("no server name specified", 0);
		return EINVAL;
	}
	if (ssn->ioc_user[0] == 0) {
		smb_error("no user name specified for server %s",
		    0, ssn->ioc_srvname);
		return EINVAL;
	}
	if (ctx->ct_minlevel >= SMBL_SHARE && sh->ioc_share[0] == 0) {
		smb_error("no share name specified for %s@%s",
		    0, ssn->ioc_user, ssn->ioc_srvname);
		return EINVAL;
	}
	error = nb_ctx_resolve(ctx->ct_nb);
	if (error)
		return error;
	if (ssn->ioc_localcs[0] == 0)
		strcpy(ssn->ioc_localcs, "default");	/* XXX: locale name ? */
	error = smb_addiconvtbl("tolower", ssn->ioc_localcs, nls_lower);
	if (error)
		return error;
	error = smb_addiconvtbl("toupper", ssn->ioc_localcs, nls_upper);
	if (error)
		return error;
	if (ssn->ioc_servercs[0] != 0) {
		for(i = 0; i < sizeof(cstbl); i++)
			cstbl[i] = i;
		nls_mem_toext(cstbl, cstbl, sizeof(cstbl));
		error = smb_addiconvtbl(ssn->ioc_servercs, ssn->ioc_localcs, cstbl);
		if (error)
			return error;
		for(i = 0; i < sizeof(cstbl); i++)
			cstbl[i] = i;
		nls_mem_toloc(cstbl, cstbl, sizeof(cstbl));
		error = smb_addiconvtbl(ssn->ioc_localcs, ssn->ioc_servercs, cstbl);
		if (error)
			return error;
	}
	if (ctx->ct_srvaddr) {
		error = nb_resolvehost_in(ctx->ct_srvaddr, &sap);
	} else {
		error = nbns_resolvename(ssn->ioc_srvname, ctx->ct_nb, &sap);
	}
	if (error) {
		smb_error("can't get server address", error);
		return error;
	}
	nn.nn_scope = ctx->ct_nb->nb_scope;
	nn.nn_type = NBT_SERVER;
	strcpy(nn.nn_name, ssn->ioc_srvname);
	error = nb_sockaddr(sap, &nn, &saserver);
	nb_snbfree(sap);
	if (error) {
		smb_error("can't allocate server address", error);
		return error;
	}
	ssn->ioc_server = (struct sockaddr*)saserver;
	if (ctx->ct_locname[0] == 0) {
		error = nb_getlocalname(ctx->ct_locname);
		if (error) {
			smb_error("can't get local name", error);
			return error;
		}
		nls_str_upper(ctx->ct_locname, ctx->ct_locname);
	}
	strcpy(nn.nn_name, ctx->ct_locname);
	nn.nn_type = NBT_WKSTA;
	nn.nn_scope = ctx->ct_nb->nb_scope;
	error = nb_sockaddr(NULL, &nn, &salocal);
	if (error) {
		nb_snbfree((struct sockaddr*)saserver);
		smb_error("can't allocate local address", error);
		return error;
	}
	ssn->ioc_local = (struct sockaddr*)salocal;
	ssn->ioc_lolen = salocal->snb_len;
	ssn->ioc_svlen = saserver->snb_len;
	if (ssn->ioc_password[0] == 0 && (ctx->ct_flags & SMBCF_NOPWD) == 0) {
		cp = getpass("Password:");
		error = smb_ctx_setpassword(ctx, cp);
		if (error)
			return error;
	}
	ctx->ct_flags |= SMBCF_RESOLVED;
	return 0;
}