diff options
Diffstat (limited to 'sqmail-4.3.07/src/srs2.c')
-rw-r--r-- | sqmail-4.3.07/src/srs2.c | 641 |
1 files changed, 0 insertions, 641 deletions
diff --git a/sqmail-4.3.07/src/srs2.c b/sqmail-4.3.07/src/srs2.c deleted file mode 100644 index 1bb431b..0000000 --- a/sqmail-4.3.07/src/srs2.c +++ /dev/null @@ -1,641 +0,0 @@ -/* Copyright (c) 2004 Shevek (srs@anarres.org) - * All rights reserved. - * - * This file is a part of libsrs2 from http://www.libsrs2.org/ - * - * Redistribution and use in source and binary forms, with or without - * modification, under the terms of either the GNU General Public - * License version 2 or the BSD license, at the discretion of the - * user. Copies of these licenses have been included in the libsrs2 - * distribution. See the the file called LICENSE for more - * information. - */ - -/* This is a minimal adapted s/qmail version; it requires complete - refactoring: - - a) Use stralloc for addresses - b) Replace stdio, str*, and mem* functions - c) Use tai64 for timestamp function - d) Remove va args - e) Reduce code by 50% -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <stdarg.h> -#include <time.h> /* time */ -#include <sys/types.h> /* tyepdefs */ -#include <sys/time.h> /* timeval / timezone struct */ -#include <string.h> /* memcpy, strcpy, memset */ -#include "srs2.h" -#include "sha1.h" - -#ifndef HAVE_STRCASECMP -# ifdef HAVE__STRICMP -# define strcasecmp _stricmp -# endif -#endif - -#ifndef HAVE_STRNCASECMP -# ifdef HAVE__STRNICMP -# define strncasecmp _strnicmp -# endif -#endif - - /* Use this */ -#define STRINGP(s) ((s != NULL) && (*(s) != '\0')) - -static const char *srs_separators = "=-+"; - -static srs_malloc_t srs_f_malloc = malloc; -static srs_realloc_t srs_f_realloc = realloc; -static srs_free_t srs_f_free = free; - -int srs_set_malloc(srs_malloc_t m, srs_realloc_t r, srs_free_t f) -{ - srs_f_malloc = m; - srs_f_realloc = r; - srs_f_free = f; - return SRS_SUCCESS; -} - -#define X(e,s) if (code == e) return s; - -const char *srs_strerror(int code) -{ - X(0,"") - /* Simple errors */ - X(SRS_SUCCESS,"Success") - X(SRS_ENOTSRSADDRESS,"Not an SRS address.") - - /* Config errors */ - X(SRS_ENOSECRETS,"No secrets in SRS configuration.") - X(SRS_ESEPARATORINVALID,"Invalid separator suggested.") - - /* Input errors */ - X(SRS_ENOSENDERATSIGN,"No at sign in sender address") - X(SRS_EBUFTOOSMALL,"Buffer too small.") - - /* Syntax errors */ - X(SRS_ENOSRS0HOST,"No host in SRS0 address.") - X(SRS_ENOSRS0USER,"No user in SRS0 address.") - X(SRS_ENOSRS0HASH,"No hash in SRS0 address.") - X(SRS_ENOSRS0STAMP,"No timestamp in SRS0 address.") - X(SRS_ENOSRS1HOST,"No host in SRS1 address.") - X(SRS_ENOSRS1USER,"No user in SRS1 address.") - X(SRS_ENOSRS1HASH,"No hash in SRS1 address.") - X(SRS_EBADTIMESTAMPCHAR,"Bad base32 character in timestamp.") - X(SRS_EHASHTOOSHORT,"Hash too short in SRS address.") - - /* SRS errors */ - X(SRS_ETIMESTAMPOUTOFDATE,"Time stamp out of date.") - X(SRS_EHASHINVALID,"Hash invalid in SRS address.") - - return "Unknown SRS error."; -} - -srs_t *srs_new() -{ - srs_t *srs = (srs_t *)srs_f_malloc(sizeof(srs_t)); - srs_init(srs); - return srs; -} - -void srs_init(srs_t *srs) -{ - memset(srs, 0, sizeof(srs_t)); - srs->secrets = NULL; - srs->numsecrets = 0; - srs->separator = '='; - srs->maxage = 21; - srs->hashlen = 4; - srs->hashmin = srs->hashlen; - srs->alwaysrewrite = FALSE; -} - -void srs_free(srs_t *srs) -{ - int i; - for (i = 0; i < srs->numsecrets; i++) { - memset(srs->secrets[i], 0, strlen(srs->secrets[i])); - srs_f_free(srs->secrets[i]); - srs->secrets[i] = '\0'; - } - srs_f_free(srs); -} - -int srs_add_secret(srs_t *srs, const char *secret) -{ - int newlen = (srs->numsecrets + 1) * sizeof(char *); - srs->secrets = (char **)srs_f_realloc(srs->secrets, newlen); - srs->secrets[srs->numsecrets++] = strdup(secret); - return SRS_SUCCESS; -} - -const char *srs_get_secret(srs_t *srs, int idx) -{ - if (idx < srs->numsecrets) - return srs->secrets[idx]; - return NULL; -} - -#define SRS_PARAM_DEFINE(n, t) \ - int srs_set_ ## n (srs_t *srs, t value) { \ - srs->n = value; \ - return SRS_SUCCESS; \ - } \ - t srs_get_ ## n (srs_t *srs) { \ - return srs->n; \ - } - -int srs_set_separator(srs_t *srs, char value) -{ - if (strchr(srs_separators, value) == NULL) - return SRS_ESEPARATORINVALID; - srs->separator = value; - return SRS_SUCCESS; -} - -char srs_get_separator(srs_t *srs) -{ - return srs->separator; -} - -SRS_PARAM_DEFINE(maxage, int) - /* XXX Check hashlen >= hashmin */ -SRS_PARAM_DEFINE(hashlen, int) -SRS_PARAM_DEFINE(hashmin, int) -SRS_PARAM_DEFINE(alwaysrewrite, srs_bool) -SRS_PARAM_DEFINE(noforward, srs_bool) -SRS_PARAM_DEFINE(noreverse, srs_bool) - -/* Don't mess with these unless you know what you're doing well - * enough to rewrite the timestamp functions. These are based on - * a 2 character timestamp. Changing these in the wild is probably - * a bad idea. */ -#define SRS_TIME_PRECISION (60 * 60 * 24) /* One day */ -#define SRS_TIME_BASEBITS 5 /* 2^5 = 32 = strlen(CHARS) */ -/* This had better be a real variable since we do arithmethic - * with it. */ -const char *SRS_TIME_BASECHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; -#define SRS_TIME_SIZE 2 -#define SRS_TIME_SLOTS (1<<(SRS_TIME_BASEBITS<<(SRS_TIME_SIZE-1))) - -int srs_timestamp_create(srs_t *srs, char *buf, time_t now) -{ - now = now / SRS_TIME_PRECISION; - buf[1] = SRS_TIME_BASECHARS[now & ((1 << SRS_TIME_BASEBITS) - 1)]; - now = now >> SRS_TIME_BASEBITS; - buf[0] = SRS_TIME_BASECHARS[now & ((1 << SRS_TIME_BASEBITS) - 1)]; - buf[2] = '\0'; - return SRS_SUCCESS; -} - -int srs_timestamp_check(srs_t *srs, const char *stamp) -{ - const char *sp; - char *bp; - int off; - time_t now; - time_t then; - - /* We had better go around this loop exactly twice! */ - then = 0; - for (sp = stamp; *sp; sp++) { - bp = strchr(SRS_TIME_BASECHARS, toupper(*sp)); - if (bp == NULL) - return SRS_EBADTIMESTAMPCHAR; - off = bp - SRS_TIME_BASECHARS; - then = (then << SRS_TIME_BASEBITS) | off; - } - - time(&now); - now = (now / SRS_TIME_PRECISION) % SRS_TIME_SLOTS; - while (now < then) - now = now + SRS_TIME_SLOTS; - - if (now <= then + srs->maxage) - return SRS_SUCCESS; - return SRS_ETIMESTAMPOUTOFDATE; -} - -const char *SRS_HASH_BASECHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - -static void srs_hash_create_v(srs_t *srs, int idx, char *buf, int nargs, va_list ap) -{ - sha1_ctx ctx; - char srshash[SHA1_DIGESTSIZE + 1]; - char *secret; - char *data; - int len; - char *lcdata; - unsigned char *hp; - char *bp; - int i; - int j; - - secret = srs->secrets[idx]; - sha1_init(&ctx); - sha1_update(&ctx, secret, strlen(secret)); - - for (i = 0; i < nargs; i++) { - data = va_arg(ap, char *); - len = strlen(data); - lcdata = alloca(len + 1); - for (j = 0; j < len; j++) { - if (isupper(data[j])) - lcdata[j] = tolower(data[j]); - else - lcdata[j] = data[j]; - } - sha1_update(&ctx, lcdata, len); - } - - sha1_final(srshash, &ctx); /* args inverted */ - srshash[SHA1_DIGESTSIZE] = '\0'; - - /* A little base64 encoding. Just a little. */ - hp = (unsigned char *)srshash; - bp = buf; - for (i = 0; i < srs->hashlen; i++) { - switch (i & 0x03) { - default: /* NOTREACHED */ - case 0: - j = (*hp >> 2); - break; - case 1: - j = ((*hp & 0x03) << 4) | - ((*(hp + 1) & 0xF0) >> 4); - hp++; - break; - case 2: - j = ((*hp & 0x0F) << 2) | - ((*(hp + 1) & 0xC0) >> 6); - hp++; - break; - case 3: - j = (*hp++ & 0x3F); - break; - } - *bp++ = SRS_HASH_BASECHARS[j]; - } - - *bp = '\0'; - buf[srs->hashlen] = '\0'; -} - -int srs_hash_create(srs_t *srs, char *buf, int nargs, ...) -{ - va_list ap; - - if (srs->numsecrets == 0) - return SRS_ENOSECRETS; - if (srs->secrets == NULL) - return SRS_ENOSECRETS; - if (srs->secrets[0] == NULL) - return SRS_ENOSECRETS; - - va_start(ap, nargs); - srs_hash_create_v(srs, 0, buf, nargs, ap); - va_end(ap); - - return SRS_SUCCESS; -} - -int srs_hash_check(srs_t *srs, char *hash, int nargs, ...) -{ - va_list ap; - char *srshash; - char *tmp; - int len; - int i; - - len = strlen(hash); - if (len < srs->hashmin) - return SRS_EHASHTOOSHORT; - if (len < srs->hashlen) { - tmp = alloca(srs->hashlen + 1); - strncpy(tmp, hash, srs->hashlen); - tmp[srs->hashlen] = '\0'; - hash = tmp; - len = srs->hashlen; - } - - for (i = 0; i < srs->numsecrets; i++) { - va_start(ap, nargs); - srshash = alloca(srs->hashlen + 1); - srs_hash_create_v(srs, i, srshash, nargs, ap); - va_end(ap); - if (strncasecmp(hash, srshash, len) == 0) - return SRS_SUCCESS; - } - - return SRS_EHASHINVALID; -} - -int srs_compile_shortcut(srs_t *srs, - char *buf, int buflen, - char *sendhost, char *senduser, - const char *aliashost) { - char *srshash; - char srsstamp[SRS_TIME_SIZE + 1]; - int len; - int ret; - - /* This never happens if we get called from guarded() */ - if ((strncasecmp(senduser, SRS0TAG, 4) == 0) && - (strchr(srs_separators, senduser[4]) != NULL)) { - sendhost = senduser + 5; - if (*sendhost == '\0') - return SRS_ENOSRS0HOST; - senduser = strchr(sendhost, SRSSEP); - if ((senduser == NULL) || (*senduser == '\0')) - return SRS_ENOSRS0USER; - } - - len = strlen(SRS0TAG) + 1 + - srs->hashlen + 1 + - SRS_TIME_SIZE + 1 + - strlen(sendhost) + 1 + strlen(senduser) - + 1 + strlen(aliashost); - if (len >= buflen) - return SRS_EBUFTOOSMALL; - - ret = srs_timestamp_create(srs, srsstamp, time(NULL)); - if (ret != SRS_SUCCESS) - return ret; - srshash = alloca(srs->hashlen + 1); - ret = srs_hash_create(srs, srshash,3, srsstamp, sendhost, senduser); - if (ret != SRS_SUCCESS) - return ret; - - sprintf(buf, SRS0TAG "%c%s%c%s%c%s%c%s@%s", srs->separator, - srshash, SRSSEP, srsstamp, SRSSEP, - sendhost, SRSSEP, senduser, - aliashost); - - return SRS_SUCCESS; -} - -int srs_compile_guarded(srs_t *srs, - char *buf, int buflen, - char *sendhost, char *senduser, - const char *aliashost) { - char *srshost; - char *srsuser; - char *srshash; - int len; - int ret; - - if ((strncasecmp(senduser, SRS1TAG, 4) == 0) && - (strchr(srs_separators, senduser[4]) != NULL)) { - /* Used as a temporary convenience var */ - srshash = senduser + 5; - if (*srshash == '\0') - return SRS_ENOSRS1HASH; - /* Used as a temporary convenience var */ - srshost = strchr(srshash, SRSSEP); - if (!STRINGP(srshost)) - return SRS_ENOSRS1HOST; - *srshost++ = '\0'; - srsuser = strchr(srshost, SRSSEP); - if (!STRINGP(srsuser)) - return SRS_ENOSRS1USER; - *srsuser++ = '\0'; - srshash = alloca(srs->hashlen + 1); - ret = srs_hash_create(srs, srshash, 2, srshost, srsuser); - if (ret != SRS_SUCCESS) - return ret; - len = strlen(SRS1TAG) + 1 + - srs->hashlen + 1 + - strlen(srshost) + 1 + strlen(srsuser) - + 1 + strlen(aliashost); - if (len >= buflen) - return SRS_EBUFTOOSMALL; - sprintf(buf, SRS1TAG "%c%s%c%s%c%s@%s", srs->separator, - srshash, SRSSEP, - srshost, SRSSEP, srsuser, - aliashost); - return SRS_SUCCESS; - } - else if ((strncasecmp(senduser, SRS0TAG, 4) == 0) && - (strchr(srs_separators, senduser[4]) != NULL)) { - srsuser = senduser + 4; - srshost = sendhost; - srshash = alloca(srs->hashlen + 1); - ret = srs_hash_create(srs, srshash, 2, srshost, srsuser); - if (ret != SRS_SUCCESS) - return ret; - len = strlen(SRS1TAG) + 1 + - srs->hashlen + 1 + - strlen(srshost) + 1 + strlen(srsuser) - + 1 + strlen(aliashost); - if (len >= buflen) - return SRS_EBUFTOOSMALL; - sprintf(buf, SRS1TAG "%c%s%c%s%c%s@%s", srs->separator, - srshash, SRSSEP, - srshost, SRSSEP, srsuser, - aliashost); - } - else { - return srs_compile_shortcut(srs, buf, buflen, - sendhost, senduser, aliashost); - } - - return SRS_SUCCESS; -} - -int srs_parse_shortcut(srs_t *srs, char *buf, int buflen, char *senduser) -{ - char *srshash; - char *srsstamp; - char *srshost; - char *srsuser; - int ret; - - if (strncasecmp(senduser, SRS0TAG, 4) == 0) { - srshash = senduser + 5; - if (!STRINGP(srshash)) - return SRS_ENOSRS0HASH; - srsstamp = strchr(srshash, SRSSEP); - if (!STRINGP(srsstamp)) - return SRS_ENOSRS0STAMP; - *srsstamp++ = '\0'; - srshost = strchr(srsstamp, SRSSEP); - if (!STRINGP(srshost)) - return SRS_ENOSRS0HOST; - *srshost++ = '\0'; - srsuser = strchr(srshost, SRSSEP); - if (!STRINGP(srsuser)) - return SRS_ENOSRS0USER; - *srsuser++ = '\0'; - ret = srs_timestamp_check(srs, srsstamp); - if (ret != SRS_SUCCESS) - return ret; - ret = srs_hash_check(srs, srshash, 3, srsstamp, - srshost, srsuser); - if (ret != SRS_SUCCESS) - return ret; - sprintf(buf, "%s@%s", srsuser, srshost); - return SRS_SUCCESS; - } - - return SRS_ENOTSRSADDRESS; -} - -int srs_parse_guarded(srs_t *srs, char *buf, int buflen, char *senduser) -{ - char *srshash; - char *srshost; - char *srsuser; - int ret; - - if (strncasecmp(senduser, SRS1TAG, 4) == 0) { - srshash = senduser + 5; - if (!STRINGP(srshash)) - return SRS_ENOSRS1HASH; - srshost = strchr(srshash, SRSSEP); - if (!STRINGP(srshost)) - return SRS_ENOSRS1HOST; - *srshost++ = '\0'; - srsuser = strchr(srshost, SRSSEP); - if (!STRINGP(srsuser)) - return SRS_ENOSRS1USER; - *srsuser++ = '\0'; - ret = srs_hash_check(srs, srshash, 2, srshost, srsuser); - if (ret != SRS_SUCCESS) - return ret; - sprintf(buf, SRS0TAG "%s@%s", srsuser, srshost); - return SRS_SUCCESS; - } - else { - return srs_parse_shortcut(srs, buf, buflen, senduser); - } -} - -int srs_forward(srs_t *srs, char *buf, int buflen, - const char *sender, const char *alias) -{ - char *senduser; - char *sendhost; - char *tmp; - int len; - - if (srs->noforward) - return SRS_ENOTREWRITTEN; - - /* This is allowed to be a plain domain */ - while ((tmp = strchr(alias, '@')) != NULL) - alias = tmp + 1; - - tmp = strchr(sender, '@'); - if (tmp == NULL) - return SRS_ENOSENDERATSIGN; - sendhost = tmp + 1; - - len = strlen(sender); - - if (! srs->alwaysrewrite) { - if (strcasecmp(sendhost, alias) == 0) { - if (strlen(sender) >= buflen) - return SRS_EBUFTOOSMALL; - strcpy(buf, sender); - return SRS_SUCCESS; - } - } - - /* Reconstruct the whole show into our alloca() buffer. */ - senduser = alloca(len + 1); - strcpy(senduser, sender); - tmp = (senduser + (tmp - sender)); - sendhost = tmp + 1; - *tmp = '\0'; - - return srs_compile_guarded(srs, buf, buflen, - sendhost, senduser, alias); -} - -int srs_forward_alloc(srs_t *srs, char **sptr, - const char *sender, const char *alias) -{ - char *buf; - int slen; - int alen; - int len; - int ret; - - if (srs->noforward) - return SRS_ENOTREWRITTEN; - - slen = strlen(sender); - alen = strlen(alias); - - /* strlen(SRSxTAG) + strlen("====+@") < 64 */ - len = slen + alen + srs->hashlen + SRS_TIME_SIZE + 64; - buf = (char *)srs_f_malloc(len); - - ret = srs_forward(srs, buf, len, sender, alias); - - if (ret == SRS_SUCCESS) - *sptr = buf; - else - srs_f_free(buf); - - return ret; -} - -int srs_reverse(srs_t *srs, char *buf, int buflen, const char *sender) -{ - char *senduser; - char *tmp; - int len; - - if (!SRS_IS_SRS_ADDRESS(sender)) - return SRS_ENOTSRSADDRESS; - - if (srs->noreverse) - return SRS_ENOTREWRITTEN; - - len = strlen(sender); - if (len >= buflen) - return SRS_EBUFTOOSMALL; - senduser = alloca(len + 1); - strcpy(senduser, sender); - - /* We don't really care about the host for reversal. */ - tmp = strchr(senduser, '@'); - if (tmp != NULL) - *tmp = '\0'; - return srs_parse_guarded(srs, buf, buflen, senduser); -} - -int srs_reverse_alloc(srs_t *srs, char **sptr, const char *sender) -{ - char *buf; - int len; - int ret; - - *sptr = NULL; - - if (!SRS_IS_SRS_ADDRESS(sender)) - return SRS_ENOTSRSADDRESS; - - if (srs->noreverse) - return SRS_ENOTREWRITTEN; - - len = strlen(sender) + 1; - buf = (char *)srs_f_malloc(len); - - ret = srs_reverse(srs, buf, len, sender); - - if (ret == SRS_SUCCESS) - *sptr = buf; - else - srs_f_free(buf); - - return ret; -} |