maddy

Fork https://github.com/foxcpp/maddy

git clone git://git.lin.moe/go/maddy.git

  1/*
  2Maddy Mail Server - Composable all-in-one email server.
  3Copyright © 2019-2022 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors
  4
  5This program is free software: you can redistribute it and/or modify
  6it under the terms of the GNU General Public License as published by
  7the Free Software Foundation, either version 3 of the License, or
  8(at your option) any later version.
  9
 10This program is distributed in the hope that it will be useful,
 11but WITHOUT ANY WARRANTY; without even the implied warranty of
 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13GNU General Public License for more details.
 14
 15You should have received a copy of the GNU General Public License
 16along with this program.  If not, see <https://www.gnu.org/licenses/>.
 17*/
 18
 19#define _POSIX_C_SOURCE 200809L
 20#include <stdio.h>
 21#include <stdlib.h>
 22#include <string.h>
 23#include <security/pam_appl.h>
 24#include "pam.h"
 25
 26static int conv_func(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) {
 27    struct pam_response *reply = malloc(sizeof(struct pam_response));
 28    if (reply == NULL) {
 29        return PAM_CONV_ERR;
 30    }
 31
 32    char* password_cpy = malloc(strlen((char*)appdata_ptr)+1);
 33    if (password_cpy == NULL) {
 34        return PAM_CONV_ERR;
 35    }
 36    memcpy(password_cpy, (char*)appdata_ptr, strlen((char*)appdata_ptr)+1);
 37
 38    reply->resp = password_cpy;
 39    reply->resp_retcode = 0;
 40
 41    // PAM frees pam_response for us.
 42    *resp = reply;
 43
 44    return PAM_SUCCESS;
 45}
 46
 47struct error_obj run_pam_auth(const char *username, char *password) {
 48    const struct pam_conv local_conv = { conv_func, password };
 49    pam_handle_t *local_auth = NULL;
 50    int status = pam_start("maddy", username, &local_conv, &local_auth);
 51    if (status != PAM_SUCCESS) {
 52        struct error_obj ret_val;
 53        ret_val.status = 2;
 54        ret_val.func_name = "pam_start";
 55        ret_val.error_msg = pam_strerror(local_auth, status);
 56        return ret_val;
 57    }
 58
 59    status = pam_authenticate(local_auth, PAM_SILENT|PAM_DISALLOW_NULL_AUTHTOK);
 60    if (status != PAM_SUCCESS) {
 61        struct error_obj ret_val;
 62        if (status == PAM_AUTH_ERR || status == PAM_USER_UNKNOWN) {
 63            ret_val.status = 1;
 64        } else {
 65            ret_val.status = 2;
 66        }
 67        ret_val.func_name = "pam_authenticate";
 68        ret_val.error_msg = pam_strerror(local_auth, status);
 69        return ret_val;
 70    }
 71
 72    status = pam_acct_mgmt(local_auth, PAM_SILENT|PAM_DISALLOW_NULL_AUTHTOK);
 73    if (status != PAM_SUCCESS) {
 74        struct error_obj ret_val;
 75        if (status == PAM_AUTH_ERR || status == PAM_USER_UNKNOWN || status == PAM_NEW_AUTHTOK_REQD) {
 76            ret_val.status = 1;
 77        } else {
 78            ret_val.status = 2;
 79        }
 80        ret_val.func_name = "pam_acct_mgmt";
 81        ret_val.error_msg = pam_strerror(local_auth, status);
 82        return ret_val;
 83    }
 84
 85    status = pam_end(local_auth, status);
 86    if (status != PAM_SUCCESS) {
 87        struct error_obj ret_val;
 88        ret_val.status = 2;
 89        ret_val.func_name = "pam_end";
 90        ret_val.error_msg = pam_strerror(local_auth, status);
 91        return ret_val;
 92    }
 93
 94    struct error_obj ret_val;
 95    ret_val.status = 0;
 96    ret_val.func_name = NULL;
 97    ret_val.error_msg = NULL;
 98    return ret_val;
 99}
100