OSSP CVS Repository

ossp - Difference in ossp-pkg/lmtp2nntp/lmtp2nntp.c versions 1.75 and 1.76
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/lmtp2nntp/lmtp2nntp.c 1.75 -> 1.76

--- lmtp2nntp.c  2001/10/09 12:08:58     1.75
+++ lmtp2nntp.c  2001/10/09 15:22:10     1.76
@@ -123,6 +123,15 @@
     l2_stream_t    *l2;
 };
 
+#define MAXACLS 32
+
+struct acl {
+    char      *acl;
+    int        not;
+    sa_addr_t *saa;
+    size_t     prefixlen;
+};
+
 typedef struct {
     l2_context_t    ctx;
     char           *progname;
@@ -143,6 +152,8 @@
     char           *option_pidfile;
     int             option_killflag;
     int             option_daemon;
+    int             option_aclc;
+    struct acl      option_acl[MAXACLS];
     l2_stream_t    *l2;
     sa_addr_t      *saaAltio;
     sa_t           *saAltio;
@@ -352,12 +363,15 @@
     lmtp_t       *lmtp = NULL;
     lmtp_io_t     lmtp_io;
     lmtp2nntp_t  *ctx = NULL;
+    int           bOk;
     int           i;             /* general purpose scratch int, index ... */
     char         *cp;            /* general purpose character pointer */
     char         *azHosts;
     size_t        asHosts;
     char         *azTimeout;
     size_t        asTimeout;
+    char         *azACL;
+    size_t        asACL;
     char         *cpHost;
     char         *cpPort;
     l2_channel_t *chPrefix;
@@ -368,6 +382,8 @@
     char         *cpName;
     char         *cpValue;
     int           nValue;
+    char         *cpAddr;
+    char         *cpPrefixLen;
 
     /* library version check (run-time) */
     if (l2_version.v_hex < L2_VERSION_HEX_REQ) {
@@ -418,6 +434,13 @@
         ctx->ns[i].rc = LMTP_ERR_UNKNOWN;
         ctx->ns[i].l2 = NULL;
     }
+    ctx->option_aclc = 0;
+    for (i = 0; i < MAXACLS; i++) {
+        ctx->option_acl[i].acl = NULL;
+        ctx->option_acl[i].not = FALSE;
+        ctx->option_acl[i].saa = NULL;
+        ctx->option_acl[i].prefixlen = 0;
+    }
     ctx->azGroupargs = NULL;
     ctx->asGroupargs = 0;
     initsession(&ctx->session);
@@ -435,7 +458,7 @@
      */
 
     /* read in the arguments */
-    while ((i = getopt(argc, argv, "D:KP:a:b:c:d:g:l:m:n:o:s:t:v")) != -1) {
+    while ((i = getopt(argc, argv, "DKP:a:b:c:d:g:l:m:n:o:s:t:v")) != -1) {
         switch (i) {
             case 'D': /*POD [B<-D>] */
                 ctx->option_daemon = TRUE;
@@ -447,7 +470,40 @@
                 ctx->option_pidfile = strdup(optarg);
                 break;
             case 'a': /*POD [B<-a> I<addr>/I<mask>[,I<addr>/I<mask>[,...]] */
-                /* FIXME */
+                if (argz_create_sep(optarg, ',', &azACL, &asACL) != 0)
+                    CU(ERR_EXECUTION);
+                cp = NULL;
+                while ((cp = argz_next(azACL, asACL, cp)) != NULL) {
+                    if (ctx->option_aclc >= MAXACLS) {
+                        fprintf(stderr, "%s:Error: Too many ACL (%d) using option -a\n", ctx->progname, ctx->option_aclc);
+                        CU(ERR_EXECUTION);
+                    }
+                    ctx->option_acl[ctx->option_aclc].acl = strdup(cp);
+                    if (cp[0] == '!') {
+                        ctx->option_acl[ctx->option_aclc].not = TRUE;
+                        cpAddr = strdup(cp+1);
+                    }
+                    else {
+                        cpAddr = strdup(cp);
+                    }
+                    if ((cpPrefixLen = strrchr(cpAddr, '/')) != NULL)
+                        *cpPrefixLen++ = NUL;
+                    else
+                        cpPrefixLen = "-1";
+                    ctx->option_acl[ctx->option_aclc].prefixlen = atoi(cpPrefixLen);
+                    if ((rc = sa_addr_create(&ctx->option_acl[ctx->option_aclc].saa)) != SA_OK) {
+                        fprintf(stderr, "%s:Error: Creating address failed for -a option (%d)\n", 
+                                ctx->progname, rc);
+                    }
+                    if ((rc = sa_addr_u2a(ctx->option_acl[ctx->option_aclc].saa, "inet://%s:0", cpAddr)) != SA_OK) {
+                        fprintf(stderr, "%s:Error: Parsing host address failed for \"%s:0\" (%d)\n", 
+                                ctx->progname, cpAddr, rc);
+                        CU(ERR_EXECUTION);
+                    }
+                    ctx->option_aclc++;
+                    free(cpAddr);
+                }
+                free(azACL);
                 break;
             case 'b': /*POD [B<-b> C<->|I<path>|I<addr>[I<:port>]] */
                 if (strcmp(optarg, "-") != 0) {
@@ -567,7 +623,7 @@
                 else
                     ctx->option_logfile = strdup("logfile");
 
-                if (l2_util_s2l(optarg, strlen(optarg), ',', &ctx->option_levelmask) != L2_OK) {
+                if (l2_util_s2l(optarg, strlen(optarg), &ctx->option_levelmask) != L2_OK) {
                     fprintf(stderr, "%s:Error: invalid level \"%s\" to option -l\n", ctx->progname, optarg);
                     CU(ERR_EXECUTION);
                 }
@@ -803,6 +859,34 @@
         CU(0);
     }
 
+    /* if no positive ACL exists (option -a) add a wildcard match-all */
+    bOk = FALSE;
+    for (i = 0; i < ctx->option_aclc; i++) {
+        if (!ctx->option_acl[i].not) {
+            bOk = TRUE;
+            break;
+        }
+    }
+    if (!bOk) {
+        if (ctx->option_aclc >= MAXACLS) {
+            fprintf(stderr, "%s:Error: Too many ACL (%d) using option -a (no space for additional fake ACL)\n", ctx->progname, ctx->option_aclc);
+            CU(ERR_EXECUTION);
+        }
+        ctx->option_acl[ctx->option_aclc].acl = "0.0.0.0/0[FAKE]";
+        ctx->option_acl[ctx->option_aclc].not = FALSE;
+        ctx->option_acl[ctx->option_aclc].prefixlen = 0;
+        if ((rc = sa_addr_create(&ctx->option_acl[ctx->option_aclc].saa)) != SA_OK) {
+            fprintf(stderr, "%s:Error: Creating fake address failed for -a option (%d)\n", 
+                    ctx->progname, rc);
+        }
+        if ((rc = sa_addr_u2a(ctx->option_acl[ctx->option_aclc].saa, "inet://0.0.0.0:0")) != SA_OK) {
+            fprintf(stderr, "%s:Error: Parsing host address failed for \"0.0.0.0:0\" (%d)\n", 
+                    ctx->progname, rc);
+            CU(ERR_EXECUTION);
+        }
+        ctx->option_aclc++;
+    }
+
     catchsignal(0, ctx);
     signal(SIGCHLD, (void(*)())catchsignal);
     signal(SIGHUP,  (void(*)())catchsignal);
@@ -873,6 +957,62 @@
         sa_timeout(ctx->saAltio, SA_TIMEOUT_READ,   ctx->option_timeout_lmtp_read,   0);
         sa_timeout(ctx->saAltio, SA_TIMEOUT_WRITE,  ctx->option_timeout_lmtp_write,  0);
         while ((rc = sa_accept(ctx->saAltio, &ctx->saaIO, &ctx->saIO)) == SA_OK) {
+
+            /* Access Control List */
+            bOk = FALSE;
+            /* check positive matches */
+            for (i = 0; i < ctx->option_aclc; i++) {
+                char *cpA1;
+                char *cpA2;
+                if (ctx->option_acl[i].not)
+                    continue;
+                sa_addr_a2u(ctx->option_acl[i].saa, &cpA1);
+                sa_addr_a2u(ctx->saaIO, &cpA2);
+                if (sa_addr_match(ctx->saaIO, ctx->option_acl[i].saa, ctx->option_acl[i].prefixlen) == SA_OK) {
+                    log4(ctx, TRACE, "positive/inclusive ACL \"%s\" (%s/%d) matching %s: OK", ctx->option_acl[i].acl, cpA1, ctx->option_acl[i].prefixlen, cpA2);
+                    bOk = TRUE;
+                    break;
+                }
+                else
+                    log4(ctx, TRACE, "positive/inclusive ACL \"%s\" (%s/%d) matching %s: FAILED", ctx->option_acl[i].acl, cpA1, ctx->option_acl[i].prefixlen, cpA2);
+                free(cpA1);
+                free(cpA2);
+            }
+            /* check negative matches */
+            for (i = 0; i < ctx->option_aclc; i++) {
+                char *cpA1;
+                char *cpA2;
+                if (!ctx->option_acl[i].not)
+                    continue;
+                sa_addr_a2u(ctx->option_acl[i].saa, &cpA1);
+                sa_addr_a2u(ctx->saaIO, &cpA2);
+                if (sa_addr_match(ctx->saaIO, ctx->option_acl[i].saa, ctx->option_acl[i].prefixlen) == SA_OK) {
+                    log4(ctx, TRACE, "negative/exclusive ACL \"%s\" (not %s/%d) matching %s: OK (stop)", ctx->option_acl[i].acl, cpA1, ctx->option_acl[i].prefixlen, cpA2);
+                    bOk = FALSE;
+                    break;
+                }
+                else {
+                    log4(ctx, TRACE, "negative/exclusive ACL \"%s\" (not %s/%d) matching %s: FAILED", ctx->option_acl[i].acl, cpA1, ctx->option_acl[i].prefixlen, cpA2);
+                }
+            }
+            if (bOk) {
+                char *cpA;
+                sa_addr_a2u(ctx->saaIO, &cpA);
+                log1(ctx, TRACE, "connection from %s accepted due to ACL", cpA); 
+                free(cpA);
+                l2_stream_flush(ctx->l2);
+            }
+            else {
+                char *cpA;
+                sa_addr_a2u(ctx->saaIO, &cpA);
+                log1(ctx, ERROR, "connection from %s refused due to ACL", cpA); 
+                free(cpA);
+                l2_stream_flush(ctx->l2);
+                sa_destroy(ctx->saIO);
+                sa_addr_destroy(ctx->saaIO);
+                continue;
+            }
+
             l2_stream_flush(ctx->l2); /* must flush before fork() */
             pid = fork();
             if (pid == -1) {

CVSTrac 2.0.1