1//+build libpam23/*4Maddy Mail Server - Composable all-in-one email server.5Copyright © 2019-2022 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors67This program is free software: you can redistribute it and/or modify8it under the terms of the GNU General Public License as published by9the Free Software Foundation, either version 3 of the License, or10(at your option) any later version.1112This program is distributed in the hope that it will be useful,13but WITHOUT ANY WARRANTY; without even the implied warranty of14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15GNU General Public License for more details.1617You should have received a copy of the GNU General Public License18along with this program. If not, see <https://www.gnu.org/licenses/>.19*/2021#define _POSIX_C_SOURCE 200809L22#include <stdio.h>23#include <stdlib.h>24#include <string.h>25#include <security/pam_appl.h>26#include "pam.h"2728static 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 }3334 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);3940 reply->resp = password_cpy;41 reply->resp_retcode = 0;4243 // PAM frees pam_response for us.44 *resp = reply;4546 return PAM_SUCCESS;47}4849struct 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 }6061 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 }7374 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 }8687 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 }9596 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