xref: /illumos-gate/usr/src/lib/libsmbfs/smb/subr.c (revision 0f1702c5201310f0529cd5abb77652e5e9b241b6)
1 /*
2  * Copyright (c) 2000, Boris Popov
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *    This product includes software developed by Boris Popov.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id: subr.c,v 1.19 2005/02/09 00:23:45 lindak Exp $
33  */
34 
35 #include <sys/types.h>
36 #include <sys/errno.h>
37 #include <sys/time.h>
38 
39 #include <unistd.h>
40 #include <ctype.h>
41 #include <string.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <stdarg.h>
45 #include <errno.h>
46 #include <sysexits.h>
47 #include <libintl.h>
48 
49 #include <netsmb/netbios.h>
50 #include <netsmb/smb_lib.h>
51 #include <netsmb/nb_lib.h>
52 #include <cflib.h>
53 #include <err.h>
54 
55 uid_t real_uid, eff_uid;
56 
57 static int smblib_initialized;
58 
59 struct rcfile *smb_rc;
60 
61 int
62 smb_lib_init(void)
63 {
64 	int error;
65 
66 	if (smblib_initialized)
67 		return (0);
68 	if ((error = nls_setlocale("")) != 0) {
69 		fprintf(stdout, dgettext(TEXT_DOMAIN,
70 		    "%s: can't initialise locale\n"), __progname);
71 		return (error);
72 	}
73 	smblib_initialized++;
74 	return (0);
75 }
76 
77 /*
78  * Private version of strerror(3C) that
79  * knows our special error codes.
80  */
81 char *
82 smb_strerror(int err)
83 {
84 	char *msg;
85 
86 	switch (err) {
87 	case EBADRPC:
88 		msg = dgettext(TEXT_DOMAIN,
89 		    "remote call failed");
90 		break;
91 	case EAUTH:
92 		msg = dgettext(TEXT_DOMAIN,
93 		    "authentication failed");
94 		break;
95 	default:
96 		msg = strerror(err);
97 		break;
98 	}
99 
100 	return (msg);
101 }
102 
103 /*
104  * Print a (descriptive) error message
105  * error values:
106  *         0 - no specific error code available;
107  *  1..32767 - system error
108  */
109 void
110 smb_error(const char *fmt, int error, ...) {
111 	va_list ap;
112 	const char *cp;
113 	int errtype;
114 
115 	fprintf(stderr, "%s: ", __progname);
116 	va_start(ap, error);
117 	vfprintf(stderr, fmt, ap);
118 	va_end(ap);
119 	if (error == -1) {
120 		error = errno;
121 		errtype = SMB_SYS_ERROR;
122 	} else {
123 		errtype = error & SMB_ERRTYPE_MASK;
124 		error &= ~SMB_ERRTYPE_MASK;
125 	}
126 	switch (errtype) {
127 	    case SMB_SYS_ERROR:
128 		if (error)
129 			fprintf(stderr, ": syserr = %s\n", smb_strerror(error));
130 		else
131 			fprintf(stderr, "\n");
132 		break;
133 	    case SMB_RAP_ERROR:
134 		fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error);
135 		break;
136 	    case SMB_NB_ERROR:
137 		cp = nb_strerror(error);
138 		if (cp == NULL)
139 			fprintf(stderr, ": nberr = unknown (0x%04x)\n", error);
140 		else
141 			fprintf(stderr, ": nberr = %s\n", cp);
142 		break;
143 	    default:
144 		fprintf(stderr, "\n");
145 	}
146 }
147 
148 char *
149 smb_printb(char *dest, int flags, const struct smb_bitname *bnp) {
150 	int first = 1;
151 
152 	strcpy(dest, "<");
153 	for (; bnp->bn_bit; bnp++) {
154 		if (flags & bnp->bn_bit) {
155 			strcat(dest, bnp->bn_name);
156 			first = 0;
157 		}
158 		if (!first && (flags & bnp[1].bn_bit))
159 			strcat(dest, "|");
160 	}
161 	strcat(dest, ">");
162 	return (dest);
163 }
164 
165 extern int home_nsmbrc;
166 
167 #ifdef DEBUG
168 #include "queue.h"
169 #include "rcfile_priv.h"
170 
171 struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname);
172 struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *keyname);
173 
174 void
175 dump_props(char *where)
176 {
177 	struct rcsection *rsp = NULL;
178 	struct rckey *rkp = NULL;
179 
180 	printf("Settings %s\n", where);
181 	SLIST_FOREACH(rsp, &smb_rc->rf_sect, rs_next) {
182 		printf("section=%s\n", rsp->rs_name);
183 		fflush(stdout);
184 
185 		SLIST_FOREACH(rkp, &rsp->rs_keys, rk_next) {
186 			printf("  key=%s, value=%s\n",
187 			    rkp->rk_name, rkp->rk_value);
188 			fflush(stdout);
189 		}
190 	}
191 }
192 #endif
193 
194 /*
195  * first read ~/.smbrc, next try to merge SMB_CFG_FILE - if that fails
196  * because SMB_CFG_FILE doesn't exist, try to merge OLD_SMB_CFG_FILE
197  */
198 int
199 smb_open_rcfile(struct smb_ctx *ctx)
200 {
201 	char *home, *fn;
202 	int error, len;
203 
204 	smb_rc = NULL;
205 #ifdef DEPRECATED
206 	fn = SMB_CFG_FILE;
207 	error = rc_merge(fn, &smb_rc);
208 	if (error == ENOENT) {
209 		/*
210 		 * OK, try to read a config file in the old location.
211 		 */
212 		fn = OLD_SMB_CFG_FILE;
213 		error = rc_merge(fn, &smb_rc);
214 	}
215 #endif
216 	fn = "/usr/sbin/sharectl get smbfs";
217 	error = rc_merge_pipe(fn, &smb_rc);
218 	if (error != 0 && error != ENOENT)
219 		fprintf(stderr, dgettext(TEXT_DOMAIN,
220 		    "Can't open %s: %s\n"), fn, smb_strerror(errno));
221 #ifdef DEBUG
222 	if (smb_debug)
223 		dump_props("after reading global repository");
224 #endif
225 
226 	home = getenv("HOME");
227 	if (home == NULL && ctx && ctx->ct_home)
228 		home = ctx->ct_home;
229 	if (home) {
230 		len = strlen(home) + 20;
231 		fn = malloc(len);
232 		snprintf(fn, len, "%s/.nsmbrc", home);
233 		home_nsmbrc = 1;
234 		error = rc_merge(fn, &smb_rc);
235 		if (error != 0 && error != ENOENT) {
236 			fprintf(stderr, dgettext(TEXT_DOMAIN,
237 			    "Can't open %s: %s\n"), fn, smb_strerror(errno));
238 		}
239 		free(fn);
240 	}
241 	home_nsmbrc = 0;
242 #ifdef DEBUG
243 	if (smb_debug)
244 		dump_props("after reading user settings");
245 #endif
246 	if (smb_rc == NULL) {
247 		return (ENOENT);
248 	}
249 	return (0);
250 }
251 
252 void
253 smb_simplecrypt(char *dst, const char *src)
254 {
255 	int ch, pos;
256 
257 	*dst++ = '$';
258 	*dst++ = '$';
259 	*dst++ = '1';
260 	pos = 27;
261 	while (*src) {
262 		ch = *src++;
263 		if (isascii(ch))
264 			ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
265 			    islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
266 		ch ^= pos;
267 		pos += 13;
268 		sprintf(dst, "%02x", ch);
269 		dst += 2;
270 	}
271 	*dst = 0;
272 }
273 
274 int
275 smb_simpledecrypt(char *dst, const char *src)
276 {
277 	char *ep, hexval[3];
278 	int len, ch, pos;
279 
280 	if (strncmp(src, "$$1", 3) != 0)
281 		return (EINVAL);
282 	src += 3;
283 	len = strlen(src);
284 	if (len & 1)
285 		return (EINVAL);
286 	len /= 2;
287 	hexval[2] = 0;
288 	pos = 27;
289 	while (len--) {
290 		hexval[0] = *src++;
291 		hexval[1] = *src++;
292 		ch = strtoul(hexval, &ep, 16);
293 		if (*ep != 0)
294 			return (EINVAL);
295 		ch ^= pos;
296 		pos += 13;
297 		if (isascii(ch))
298 			ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
299 			    islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
300 		*dst++ = ch;
301 	}
302 	*dst = 0;
303 	return (0);
304 }
305 
306 #undef __progname
307 
308 char *__progname = NULL;
309 
310 char *
311 smb_getprogname()
312 {
313 	char *p;
314 
315 	if (__progname == NULL) {
316 		__progname = (char *)getexecname();
317 		if ((p = strrchr(__progname, '/')) != 0)
318 			__progname = p + 1;
319 	}
320 	return (__progname);
321 }
322