summaryrefslogtreecommitdiff
path: root/sqmail-4.3.07/src/srs2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sqmail-4.3.07/src/srs2.c')
-rw-r--r--sqmail-4.3.07/src/srs2.c641
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;
-}