maddy

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

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

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