1/*2Maddy Mail Server - Composable all-in-one email server.3Copyright © 2019-2022 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors45This program is free software: you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation, either version 3 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program. If not, see <https://www.gnu.org/licenses/>.17*/1819#define _POSIX_C_SOURCE 200809L20#include <stdio.h>21#include <stdlib.h>22#include <string.h>23#include <security/pam_appl.h>24#include "pam.h"2526static 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 }3132 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);3738 reply->resp = password_cpy;39 reply->resp_retcode = 0;4041 // PAM frees pam_response for us.42 *resp = reply;4344 return PAM_SUCCESS;45}4647struct 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 }5859 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 }7172 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 }8485 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 }9394 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