blob: 7b79cd7ae5134f65dcc28f92fb942ce7b46d12a4 [file] [log] [blame]
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +05301/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
Patrick Williams9e7627a2023-05-10 07:51:06 -050017#include <stdarg.h>
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +053018#include <stdio.h>
19#include <stdlib.h>
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +053020#include <string.h>
Patrick Williams9e7627a2023-05-10 07:51:06 -050021#include <syslog.h>
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +053022
23#include <security/pam_ext.h>
24#include <security/pam_modules.h>
25#include <security/pam_modutil.h>
26
27#define MAX_SPEC_GRP_PASS_LENGTH 20
28#define MAX_SPEC_GRP_USER_LENGTH 16
29
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +053030/*
31 * This module is intended to verify special group user password matches the
32 * restrictions needed.
33 *
34 * Note: Other than for pam_chauthtok(), pam_ipmicheck module should not be
35 * used for other purpose like authentication, session & account management.
36 * This module has to be used along with pam_ipmisave module, which will save
37 * the passwords of the special group users.
38 */
39
Vernon Mauerybb717162023-06-27 10:22:23 -070040static const char *get_option(const char *option, int argc, const char **argv)
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +053041{
42 int i = 0;
43 size_t len = strlen(option);
44
45 for (i = 0; i < argc; ++i) {
46 if (strncmp(option, argv[i], len) == 0) {
47 if (argv[i][len] == '=') {
48 return &argv[i][len + 1];
49 }
50 }
51 }
52 return NULL;
53}
54
55/* Password Management API's */
56
57int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
58{
59 int retval = -1;
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +053060 const char *user = NULL;
61 const char *pass_new = NULL, *pass_old = NULL;
Vernon Mauerybb717162023-06-27 10:22:23 -070062 const char *spec_grp_name = get_option("spec_grp_name", argc, argv);
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +053063
64 if (spec_grp_name == NULL) {
65 return PAM_IGNORE;
66 }
Vernon Mauerybb717162023-06-27 10:22:23 -070067 pam_syslog(pamh, LOG_DEBUG, "Special group name is %s", spec_grp_name);
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +053068 if (flags & PAM_PRELIM_CHECK) {
69 // send success to verify other stacked modules prelim check.
70 pam_syslog(pamh, LOG_DEBUG, "PRELIM_CHECK Called");
71 return PAM_SUCCESS;
72 }
73
74 // Read new password.
75 // Note: Subsequent modules must use stacked password option use_authtok
76 retval = pam_get_authtok(pamh, PAM_AUTHTOK, &pass_new, NULL);
77 if (retval != PAM_SUCCESS) {
78 pam_syslog(pamh, LOG_ERR,
79 "password - unable to get new password");
80 return retval;
81 }
82
83 retval = pam_get_user(pamh, &user, NULL);
84 if (retval != PAM_SUCCESS) {
85 return retval;
86 }
87
88 struct group *grp;
89 int spec_grp_usr = 0;
90 // Verify whether the user belongs to special group.
91 grp = pam_modutil_getgrnam(pamh, spec_grp_name);
92 if (grp != NULL) {
93 while (*(grp->gr_mem) != NULL) {
94 if (strcmp(user, *grp->gr_mem) == 0) {
95 spec_grp_usr = 1;
96 break;
97 }
98 (grp->gr_mem)++;
99 }
100 }
101
102 if (spec_grp_usr) {
103 // verify the new password is acceptable.
Jiaqing Zhaoa80864a2022-04-04 16:36:35 +0800104 size_t pass_len = strlen(pass_new);
105 size_t user_len = strlen(user);
Patrick Williams9e7627a2023-05-10 07:51:06 -0500106 if (pass_len > MAX_SPEC_GRP_PASS_LENGTH ||
107 user_len > MAX_SPEC_GRP_USER_LENGTH) {
108 pam_syslog(pamh, LOG_ERR,
109 "Password length (%zu) / User name length "
110 "(%zu) is not acceptable for IPMI",
111 pass_len, user_len);
112 pam_error(pamh,
113 "Username %zu / Password %zu exceeds IPMI "
114 "16/20 limit",
115 user_len, pass_len);
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +0530116 pass_new = pass_old = NULL;
Jiaqing Zhaoe3771e82022-04-02 18:02:25 +0800117 return PAM_AUTHTOK_ERR;
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +0530118 }
119 }
120
121 return PAM_SUCCESS;
122}
123
124/* end of module definition */