Download | Plain Text | Line Numbers


/*
 * Copyright (c) 2016-2024 Manuel Mausz
 */
 
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/file.h>
#include <db.h>
 
void db_error_cb(const DB_ENV *dbenv, const char *prefix, const char *msg)
{
  fprintf(stderr, "%s: %s\n", prefix, msg);
}
 
int main()
{
  char *user = getenv("SMTPAUTHUSER");
  if (user == NULL || strlen(user) == 0)
    return 0;
 
  char *dbfile = getenv("LOCKUSERDB");
  if (dbfile == NULL)
    dbfile = "control/lockedusers.db";
 
  int fdlock = open(dbfile, O_RDONLY);
  if (fdlock < 0)
  {
    perror("Unable to open database file");
    return 0;
  }
 
  if (flock(fdlock, LOCK_SH) < 0)
  {
    perror("Unable to shared-lock database file");
    goto err_unlock;
  }
 
  DB *db;
  int err = db_create(&db, NULL, 0);
  if (err != 0)
  {
    fprintf(stderr, "Unable to create db env: %s\n", db_strerror(err));
    goto err_unlock;
  }
 
  db->set_errpfx(db, "lockuser");
  db->set_errcall(db, db_error_cb);
 
  if ((err = db->open(db, NULL, dbfile, NULL, DB_UNKNOWN,  DB_RDONLY, 0600)) != 0)
  {
    (void)fprintf(stderr, "Unable to open database: %s\n", db_strerror(err));
    goto err_close_db;
  }
 
  DBT key = { .data = user, .size = strlen(user) };
  err = db->exists(db, NULL, &key, 0);
  if (err == 0)
  {
    puts("E550 YOUR ACCOUNT HAS BEEN LOCKED - PLEASE CONTACT YOUR POSTMASTER");
    fprintf(stderr, "block: smtp user %s has been blocked\n", user);
  }
  else if (err != DB_NOTFOUND && err != DB_KEYEMPTY)
  {
    (void)fprintf(stderr, "Unable to read from database: %s\n", db_strerror(err));
  }
 
err_close_db:
  (void)db->close(db, 0);
err_unlock:
  (void)close(fdlock);
  return 0;
}