Skip to content

Commit cf94882

Browse files
committed
auth/pam: Fix double-free crash
conv_func may be called multiple times and should return a unique pam_response each time. Closes #272.
1 parent 7ee6a39 commit cf94882

File tree

3 files changed

+54
-28
lines changed

3 files changed

+54
-28
lines changed

cmd/maddy-pam-helper/pam.c

+18-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
//+build libpam
2-
31
/*
42
Maddy Mail Server - Composable all-in-one email server.
53
Copyright © 2019-2022 Max Mazurov <[email protected]>, Maddy Mail Server contributors
@@ -21,28 +19,33 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
2119
#define _POSIX_C_SOURCE 200809L
2220
#include <stdio.h>
2321
#include <stdlib.h>
22+
#include <string.h>
2423
#include <security/pam_appl.h>
2524
#include "pam.h"
2625

2726
static int conv_func(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) {
28-
*resp = (struct pam_response*)appdata_ptr;
29-
return PAM_SUCCESS;
30-
}
31-
32-
struct error_obj run_pam_auth(const char *username, char *password) {
33-
// PAM frees pam_response for us.
3427
struct pam_response *reply = malloc(sizeof(struct pam_response));
3528
if (reply == NULL) {
36-
struct error_obj ret_val;
37-
ret_val.status = 2;
38-
ret_val.func_name = "malloc";
39-
ret_val.error_msg = "Out of memory";
40-
return ret_val;
29+
return PAM_CONV_ERR;
4130
}
42-
reply->resp = password;
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;
4339
reply->resp_retcode = 0;
4440

45-
const struct pam_conv local_conv = { conv_func, reply };
41+
// PAM frees pam_response for us.
42+
*resp = reply;
43+
44+
return PAM_SUCCESS;
45+
}
46+
47+
struct error_obj run_pam_auth(const char *username, char *password) {
48+
const struct pam_conv local_conv = { conv_func, password };
4649
pam_handle_t *local_auth = NULL;
4750
int status = pam_start("maddy", username, &local_conv, &local_auth);
4851
if (status != PAM_SUCCESS) {

cmd/maddy-pam-helper/pam.h

+18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
/*
2+
Maddy Mail Server - Composable all-in-one email server.
3+
Copyright © 2019-2020 Max Mazurov <[email protected]>, Maddy Mail Server contributors
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
119
#pragma once
220

321
struct error_obj {

internal/auth/pam/pam.c

+18-13
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,33 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
2121
#define _POSIX_C_SOURCE 200809L
2222
#include <stdio.h>
2323
#include <stdlib.h>
24+
#include <string.h>
2425
#include <security/pam_appl.h>
2526
#include "pam.h"
2627

2728
static int conv_func(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) {
28-
*resp = (struct pam_response*)appdata_ptr;
29-
return PAM_SUCCESS;
30-
}
31-
32-
struct error_obj run_pam_auth(const char *username, char *password) {
33-
// PAM frees pam_response for us.
3429
struct pam_response *reply = malloc(sizeof(struct pam_response));
3530
if (reply == NULL) {
36-
struct error_obj ret_val;
37-
ret_val.status = 2;
38-
ret_val.func_name = "malloc";
39-
ret_val.error_msg = "Out of memory";
40-
return ret_val;
31+
return PAM_CONV_ERR;
4132
}
42-
reply->resp = password;
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;
4341
reply->resp_retcode = 0;
4442

45-
const struct pam_conv local_conv = { conv_func, reply };
43+
// PAM frees pam_response for us.
44+
*resp = reply;
45+
46+
return PAM_SUCCESS;
47+
}
48+
49+
struct error_obj run_pam_auth(const char *username, char *password) {
50+
const struct pam_conv local_conv = { conv_func, password };
4651
pam_handle_t *local_auth = NULL;
4752
int status = pam_start("maddy", username, &local_conv, &local_auth);
4853
if (status != PAM_SUCCESS) {

0 commit comments

Comments
 (0)