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