1 /* $OpenBSD: util.c,v 1.138 2018/10/31 16:32:12 gilles Exp $ */ 2 3 /* 4 * Copyright (c) 2000,2001 Markus Friedl. All rights reserved. 5 * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> 6 * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net> 7 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/types.h> 23 #include <sys/queue.h> 24 #include <sys/tree.h> 25 #include <sys/socket.h> 26 #include <sys/stat.h> 27 #include <sys/resource.h> 28 29 #include <netinet/in.h> 30 #include <arpa/inet.h> 31 32 #include <ctype.h> 33 #include <errno.h> 34 #include <event.h> 35 #include <fcntl.h> 36 #include <fts.h> 37 #include <imsg.h> 38 #include <inttypes.h> 39 #include <libgen.h> 40 #include <netdb.h> 41 #include <pwd.h> 42 #include <limits.h> 43 #include <resolv.h> 44 #include <stdarg.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <syslog.h> 49 #include <time.h> 50 #include <unistd.h> 51 52 #include "smtpd.h" 53 #include "log.h" 54 55 const char *log_in6addr(const struct in6_addr *); 56 const char *log_sockaddr(struct sockaddr *); 57 static int parse_mailname_file(char *, size_t); 58 59 int tracing = 0; 60 int foreground_log = 0; 61 62 void * 63 xmalloc(size_t size) 64 { 65 void *r; 66 67 if ((r = malloc(size)) == NULL) 68 fatal("malloc"); 69 70 return (r); 71 } 72 73 void * 74 xcalloc(size_t nmemb, size_t size) 75 { 76 void *r; 77 78 if ((r = calloc(nmemb, size)) == NULL) 79 fatal("calloc"); 80 81 return (r); 82 } 83 84 char * 85 xstrdup(const char *str) 86 { 87 char *r; 88 89 if ((r = strdup(str)) == NULL) 90 fatal("strdup"); 91 92 return (r); 93 } 94 95 void * 96 xmemdup(const void *ptr, size_t size) 97 { 98 void *r; 99 100 if ((r = malloc(size)) == NULL) 101 fatal("malloc"); 102 103 memmove(r, ptr, size); 104 105 return (r); 106 } 107 108 int 109 xasprintf(char **ret, const char *format, ...) 110 { 111 int r; 112 va_list ap; 113 114 va_start(ap, format); 115 r = vasprintf(ret, format, ap); 116 va_end(ap); 117 if (r == -1) 118 fatal("vasprintf"); 119 120 return (r); 121 } 122 123 124 #if !defined(NO_IO) 125 int 126 io_xprintf(struct io *io, const char *fmt, ...) 127 { 128 va_list ap; 129 int len; 130 131 va_start(ap, fmt); 132 len = io_vprintf(io, fmt, ap); 133 va_end(ap); 134 if (len == -1) 135 fatal("io_xprintf(%p, %s, ...)", io, fmt); 136 137 return len; 138 } 139 140 int 141 io_xprint(struct io *io, const char *str) 142 { 143 int len; 144 145 len = io_print(io, str); 146 if (len == -1) 147 fatal("io_xprint(%p, %s, ...)", io, str); 148 149 return len; 150 } 151 #endif 152 153 char * 154 strip(char *s) 155 { 156 size_t l; 157 158 while (isspace((unsigned char)*s)) 159 s++; 160 161 for (l = strlen(s); l; l--) { 162 if (!isspace((unsigned char)s[l-1])) 163 break; 164 s[l-1] = '\0'; 165 } 166 167 return (s); 168 } 169 170 int 171 bsnprintf(char *str, size_t size, const char *format, ...) 172 { 173 int ret; 174 va_list ap; 175 176 va_start(ap, format); 177 ret = vsnprintf(str, size, format, ap); 178 va_end(ap); 179 if (ret == -1 || ret >= (int)size) 180 return 0; 181 182 return 1; 183 } 184 185 186 static int 187 mkdirs_component(char *path, mode_t mode) 188 { 189 struct stat sb; 190 191 if (stat(path, &sb) == -1) { 192 if (errno != ENOENT) 193 return 0; 194 if (mkdir(path, mode | S_IWUSR | S_IXUSR) == -1) 195 return 0; 196 } 197 else if (!S_ISDIR(sb.st_mode)) 198 return 0; 199 200 return 1; 201 } 202 203 int 204 mkdirs(char *path, mode_t mode) 205 { 206 char buf[PATH_MAX]; 207 int i = 0; 208 int done = 0; 209 char *p; 210 211 /* absolute path required */ 212 if (*path != '/') 213 return 0; 214 215 /* make sure we don't exceed PATH_MAX */ 216 if (strlen(path) >= sizeof buf) 217 return 0; 218 219 memset(buf, 0, sizeof buf); 220 for (p = path; *p; p++) { 221 if (*p == '/') { 222 if (buf[0] != '\0') 223 if (!mkdirs_component(buf, mode)) 224 return 0; 225 while (*p == '/') 226 p++; 227 buf[i++] = '/'; 228 buf[i++] = *p; 229 if (*p == '\0' && ++done) 230 break; 231 continue; 232 } 233 buf[i++] = *p; 234 } 235 if (!done) 236 if (!mkdirs_component(buf, mode)) 237 return 0; 238 239 if (chmod(path, mode) == -1) 240 return 0; 241 242 return 1; 243 } 244 245 int 246 ckdir(const char *path, mode_t mode, uid_t owner, gid_t group, int create) 247 { 248 char mode_str[12]; 249 int ret; 250 struct stat sb; 251 252 if (stat(path, &sb) == -1) { 253 if (errno != ENOENT || create == 0) { 254 log_warn("stat: %s", path); 255 return (0); 256 } 257 258 /* chmod is deferred to avoid umask effect */ 259 if (mkdir(path, 0) == -1) { 260 log_warn("mkdir: %s", path); 261 return (0); 262 } 263 264 if (chown(path, owner, group) == -1) { 265 log_warn("chown: %s", path); 266 return (0); 267 } 268 269 if (chmod(path, mode) == -1) { 270 log_warn("chmod: %s", path); 271 return (0); 272 } 273 274 if (stat(path, &sb) == -1) { 275 log_warn("stat: %s", path); 276 return (0); 277 } 278 } 279 280 ret = 1; 281 282 /* check if it's a directory */ 283 if (!S_ISDIR(sb.st_mode)) { 284 ret = 0; 285 log_warnx("%s is not a directory", path); 286 } 287 288 /* check that it is owned by owner/group */ 289 if (sb.st_uid != owner) { 290 ret = 0; 291 log_warnx("%s is not owned by uid %d", path, owner); 292 } 293 if (sb.st_gid != group) { 294 ret = 0; 295 log_warnx("%s is not owned by gid %d", path, group); 296 } 297 298 /* check permission */ 299 if ((sb.st_mode & 07777) != mode) { 300 ret = 0; 301 strmode(mode, mode_str); 302 mode_str[10] = '\0'; 303 log_warnx("%s must be %s (%o)", path, mode_str + 1, mode); 304 } 305 306 return ret; 307 } 308 309 int 310 rmtree(char *path, int keepdir) 311 { 312 char *path_argv[2]; 313 FTS *fts; 314 FTSENT *e; 315 int ret, depth; 316 317 path_argv[0] = path; 318 path_argv[1] = NULL; 319 ret = 0; 320 depth = 0; 321 322 fts = fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL); 323 if (fts == NULL) { 324 log_warn("fts_open: %s", path); 325 return (-1); 326 } 327 328 while ((e = fts_read(fts)) != NULL) { 329 switch (e->fts_info) { 330 case FTS_D: 331 depth++; 332 break; 333 case FTS_DP: 334 case FTS_DNR: 335 depth--; 336 if (keepdir && depth == 0) 337 continue; 338 if (rmdir(e->fts_path) == -1) { 339 log_warn("rmdir: %s", e->fts_path); 340 ret = -1; 341 } 342 break; 343 344 case FTS_F: 345 if (unlink(e->fts_path) == -1) { 346 log_warn("unlink: %s", e->fts_path); 347 ret = -1; 348 } 349 } 350 } 351 352 fts_close(fts); 353 354 return (ret); 355 } 356 357 int 358 mvpurge(char *from, char *to) 359 { 360 size_t n; 361 int retry; 362 const char *sep; 363 char buf[PATH_MAX]; 364 365 if ((n = strlen(to)) == 0) 366 fatalx("to is empty"); 367 368 sep = (to[n - 1] == '/') ? "" : "/"; 369 retry = 0; 370 371 again: 372 (void)snprintf(buf, sizeof buf, "%s%s%u", to, sep, arc4random()); 373 if (rename(from, buf) == -1) { 374 /* ENOTDIR has actually 2 meanings, and incorrect input 375 * could lead to an infinite loop. Consider that after 376 * 20 tries something is hopelessly wrong. 377 */ 378 if (errno == ENOTEMPTY || errno == EISDIR || errno == ENOTDIR) { 379 if ((retry++) >= 20) 380 return (-1); 381 goto again; 382 } 383 return -1; 384 } 385 386 return 0; 387 } 388 389 390 int 391 mktmpfile(void) 392 { 393 char path[PATH_MAX]; 394 int fd; 395 396 if (!bsnprintf(path, sizeof(path), "%s/smtpd.XXXXXXXXXX", 397 PATH_TEMPORARY)) { 398 log_warn("snprintf"); 399 fatal("exiting"); 400 } 401 402 if ((fd = mkstemp(path)) == -1) { 403 log_warn("cannot create temporary file %s", path); 404 fatal("exiting"); 405 } 406 unlink(path); 407 return (fd); 408 } 409 410 411 /* Close file, signifying temporary error condition (if any) to the caller. */ 412 int 413 safe_fclose(FILE *fp) 414 { 415 if (ferror(fp)) { 416 fclose(fp); 417 return 0; 418 } 419 if (fflush(fp)) { 420 fclose(fp); 421 if (errno == ENOSPC) 422 return 0; 423 fatal("safe_fclose: fflush"); 424 } 425 if (fsync(fileno(fp))) 426 fatal("safe_fclose: fsync"); 427 if (fclose(fp)) 428 fatal("safe_fclose: fclose"); 429 430 return 1; 431 } 432 433 int 434 hostname_match(const char *hostname, const char *pattern) 435 { 436 while (*pattern != '\0' && *hostname != '\0') { 437 if (*pattern == '*') { 438 while (*pattern == '*') 439 pattern++; 440 while (*hostname != '\0' && 441 tolower((unsigned char)*hostname) != 442 tolower((unsigned char)*pattern)) 443 hostname++; 444 continue; 445 } 446 447 if (tolower((unsigned char)*pattern) != 448 tolower((unsigned char)*hostname)) 449 return 0; 450 pattern++; 451 hostname++; 452 } 453 454 return (*hostname == '\0' && *pattern == '\0'); 455 } 456 457 int 458 mailaddr_match(const struct mailaddr *maddr1, const struct mailaddr *maddr2) 459 { 460 struct mailaddr m1 = *maddr1; 461 struct mailaddr m2 = *maddr2; 462 char *p; 463 464 /* catchall */ 465 if (m2.user[0] == '\0' && m2.domain[0] == '\0') 466 return 1; 467 468 if (m2.domain[0] && !hostname_match(m1.domain, m2.domain)) 469 return 0; 470 471 if (m2.user[0]) { 472 /* if address from table has a tag, we must respect it */ 473 if (strchr(m2.user, *env->sc_subaddressing_delim) == NULL) { 474 /* otherwise, strip tag from session address if any */ 475 p = strchr(m1.user, *env->sc_subaddressing_delim); 476 if (p) 477 *p = '\0'; 478 } 479 if (strcasecmp(m1.user, m2.user)) 480 return 0; 481 } 482 return 1; 483 } 484 485 int 486 valid_localpart(const char *s) 487 { 488 #define IS_ATEXT(c) (isalnum((unsigned char)(c)) || strchr(MAILADDR_ALLOWED, (c))) 489 nextatom: 490 if (!IS_ATEXT(*s) || *s == '\0') 491 return 0; 492 while (*(++s) != '\0') { 493 if (*s == '.') 494 break; 495 if (IS_ATEXT(*s)) 496 continue; 497 return 0; 498 } 499 if (*s == '.') { 500 s++; 501 goto nextatom; 502 } 503 return 1; 504 } 505 506 int 507 valid_domainpart(const char *s) 508 { 509 struct in_addr ina; 510 struct in6_addr ina6; 511 char *c, domain[SMTPD_MAXDOMAINPARTSIZE]; 512 const char *p; 513 514 if (*s == '[') { 515 if (strncasecmp("[IPv6:", s, 6) == 0) 516 p = s + 6; 517 else 518 p = s + 1; 519 520 if (strlcpy(domain, p, sizeof domain) >= sizeof domain) 521 return 0; 522 523 c = strchr(domain, (int)']'); 524 if (!c || c[1] != '\0') 525 return 0; 526 527 *c = '\0'; 528 529 if (inet_pton(AF_INET6, domain, &ina6) == 1) 530 return 1; 531 if (inet_pton(AF_INET, domain, &ina) == 1) 532 return 1; 533 534 return 0; 535 } 536 537 if (*s == '\0') 538 return 0; 539 540 return res_hnok(s); 541 } 542 543 int 544 valid_smtp_response(const char *s) 545 { 546 if (strlen(s) < 5) 547 return 0; 548 549 if ((s[0] < '2' || s[0] > '5') || 550 (s[1] < '0' || s[1] > '9') || 551 (s[2] < '0' || s[2] > '9') || 552 (s[3] != ' ')) 553 return 0; 554 555 return 1; 556 } 557 558 int 559 secure_file(int fd, char *path, char *userdir, uid_t uid, int mayread) 560 { 561 char buf[PATH_MAX]; 562 char homedir[PATH_MAX]; 563 struct stat st; 564 char *cp; 565 566 if (realpath(path, buf) == NULL) 567 return 0; 568 569 if (realpath(userdir, homedir) == NULL) 570 homedir[0] = '\0'; 571 572 /* Check the open file to avoid races. */ 573 if (fstat(fd, &st) < 0 || 574 !S_ISREG(st.st_mode) || 575 st.st_uid != uid || 576 (st.st_mode & (mayread ? 022 : 066)) != 0) 577 return 0; 578 579 /* For each component of the canonical path, walking upwards. */ 580 for (;;) { 581 if ((cp = dirname(buf)) == NULL) 582 return 0; 583 (void)strlcpy(buf, cp, sizeof(buf)); 584 585 if (stat(buf, &st) < 0 || 586 (st.st_uid != 0 && st.st_uid != uid) || 587 (st.st_mode & 022) != 0) 588 return 0; 589 590 /* We can stop checking after reaching homedir level. */ 591 if (strcmp(homedir, buf) == 0) 592 break; 593 594 /* 595 * dirname should always complete with a "/" path, 596 * but we can be paranoid and check for "." too 597 */ 598 if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) 599 break; 600 } 601 602 return 1; 603 } 604 605 void 606 addargs(arglist *args, char *fmt, ...) 607 { 608 va_list ap; 609 char *cp; 610 uint nalloc; 611 int r; 612 char **tmp; 613 614 va_start(ap, fmt); 615 r = vasprintf(&cp, fmt, ap); 616 va_end(ap); 617 if (r == -1) 618 fatal("addargs: argument too long"); 619 620 nalloc = args->nalloc; 621 if (args->list == NULL) { 622 nalloc = 32; 623 args->num = 0; 624 } else if (args->num+2 >= nalloc) 625 nalloc *= 2; 626 627 tmp = reallocarray(args->list, nalloc, sizeof(char *)); 628 if (tmp == NULL) 629 fatal("addargs: reallocarray"); 630 args->list = tmp; 631 args->nalloc = nalloc; 632 args->list[args->num++] = cp; 633 args->list[args->num] = NULL; 634 } 635 636 int 637 lowercase(char *buf, const char *s, size_t len) 638 { 639 if (len == 0) 640 return 0; 641 642 if (strlcpy(buf, s, len) >= len) 643 return 0; 644 645 while (*buf != '\0') { 646 *buf = tolower((unsigned char)*buf); 647 buf++; 648 } 649 650 return 1; 651 } 652 653 int 654 uppercase(char *buf, const char *s, size_t len) 655 { 656 if (len == 0) 657 return 0; 658 659 if (strlcpy(buf, s, len) >= len) 660 return 0; 661 662 while (*buf != '\0') { 663 *buf = toupper((unsigned char)*buf); 664 buf++; 665 } 666 667 return 1; 668 } 669 670 void 671 xlowercase(char *buf, const char *s, size_t len) 672 { 673 if (len == 0) 674 fatalx("lowercase: len == 0"); 675 676 if (!lowercase(buf, s, len)) 677 fatalx("lowercase: truncation"); 678 } 679 680 uint64_t 681 generate_uid(void) 682 { 683 static uint32_t id; 684 static uint8_t inited; 685 uint64_t uid; 686 687 if (!inited) { 688 id = arc4random(); 689 inited = 1; 690 } 691 while ((uid = ((uint64_t)(id++) << 32 | arc4random())) == 0) 692 ; 693 694 return (uid); 695 } 696 697 int 698 session_socket_error(int fd) 699 { 700 int error; 701 socklen_t len; 702 703 len = sizeof(error); 704 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) 705 fatal("session_socket_error: getsockopt"); 706 707 return (error); 708 } 709 710 const char * 711 parse_smtp_response(char *line, size_t len, char **msg, int *cont) 712 { 713 if (len >= LINE_MAX) 714 return "line too long"; 715 716 if (len > 3) { 717 if (msg) 718 *msg = line + 4; 719 if (cont) 720 *cont = (line[3] == '-'); 721 } else if (len == 3) { 722 if (msg) 723 *msg = line + 3; 724 if (cont) 725 *cont = 0; 726 } else 727 return "line too short"; 728 729 /* validate reply code */ 730 if (line[0] < '2' || line[0] > '5' || !isdigit((unsigned char)line[1]) || 731 !isdigit((unsigned char)line[2])) 732 return "reply code out of range"; 733 734 return NULL; 735 } 736 737 static int 738 parse_mailname_file(char *hostname, size_t len) 739 { 740 FILE *fp; 741 char *buf = NULL; 742 size_t bufsz = 0; 743 ssize_t buflen; 744 745 if ((fp = fopen(MAILNAME_FILE, "r")) == NULL) 746 return 1; 747 748 if ((buflen = getline(&buf, &bufsz, fp)) == -1) 749 goto error; 750 751 if (buf[buflen - 1] == '\n') 752 buf[buflen - 1] = '\0'; 753 754 if (strlcpy(hostname, buf, len) >= len) { 755 fprintf(stderr, MAILNAME_FILE " entry too long"); 756 goto error; 757 } 758 759 return 0; 760 error: 761 fclose(fp); 762 free(buf); 763 return 1; 764 } 765 766 int 767 getmailname(char *hostname, size_t len) 768 { 769 struct addrinfo hints, *res = NULL; 770 int error; 771 772 /* Try MAILNAME_FILE first */ 773 if (parse_mailname_file(hostname, len) == 0) 774 return 0; 775 776 /* Next, gethostname(3) */ 777 if (gethostname(hostname, len) == -1) { 778 fprintf(stderr, "getmailname: gethostname() failed\n"); 779 return -1; 780 } 781 782 if (strchr(hostname, '.') != NULL) 783 return 0; 784 785 /* Canonicalize if domain part is missing */ 786 memset(&hints, 0, sizeof hints); 787 hints.ai_family = PF_UNSPEC; 788 hints.ai_flags = AI_CANONNAME; 789 error = getaddrinfo(hostname, NULL, &hints, &res); 790 if (error) 791 return 0; /* Continue with non-canon hostname */ 792 793 if (strlcpy(hostname, res->ai_canonname, len) >= len) { 794 fprintf(stderr, "hostname too long"); 795 return -1; 796 } 797 798 freeaddrinfo(res); 799 return 0; 800 } 801 802 int 803 base64_encode(unsigned char const *src, size_t srclen, 804 char *dest, size_t destsize) 805 { 806 return __b64_ntop(src, srclen, dest, destsize); 807 } 808 809 int 810 base64_decode(char const *src, unsigned char *dest, size_t destsize) 811 { 812 return __b64_pton(src, dest, destsize); 813 } 814 815 void 816 log_trace(int mask, const char *emsg, ...) 817 { 818 va_list ap; 819 820 if (tracing & mask) { 821 va_start(ap, emsg); 822 vlog(LOG_DEBUG, emsg, ap); 823 va_end(ap); 824 } 825 } 826 827 void 828 log_trace_verbose(int v) 829 { 830 tracing = v; 831 832 /* Set debug logging in log.c */ 833 log_setverbose(v & TRACE_DEBUG ? 2 : foreground_log); 834 } 835