blob: afd870469909410324e7f507c8a7a9cf288d8fbd [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
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +053040static const char *get_option(const pam_handle_t *pamh, const char *option,
41 int argc, const char **argv)
42{
43 int i = 0;
44 size_t len = strlen(option);
45
46 for (i = 0; i < argc; ++i) {
47 if (strncmp(option, argv[i], len) == 0) {
48 if (argv[i][len] == '=') {
49 return &argv[i][len + 1];
50 }
51 }
52 }
53 return NULL;
54}
55
56/* Password Management API's */
57
58int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
59{
60 int retval = -1;
61 const void *item = NULL;
62 const char *user = NULL;
63 const char *pass_new = NULL, *pass_old = NULL;
64 const char *spec_grp_name =
Patrick Williams9e7627a2023-05-10 07:51:06 -050065 get_option(pamh, "spec_grp_name", argc, argv);
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +053066
67 pam_syslog(pamh, LOG_DEBUG, "Special group name is %s", spec_grp_name);
68
69 if (spec_grp_name == NULL) {
70 return PAM_IGNORE;
71 }
72 if (flags & PAM_PRELIM_CHECK) {
73 // send success to verify other stacked modules prelim check.
74 pam_syslog(pamh, LOG_DEBUG, "PRELIM_CHECK Called");
75 return PAM_SUCCESS;
76 }
77
78 // Read new password.
79 // Note: Subsequent modules must use stacked password option use_authtok
80 retval = pam_get_authtok(pamh, PAM_AUTHTOK, &pass_new, NULL);
81 if (retval != PAM_SUCCESS) {
82 pam_syslog(pamh, LOG_ERR,
83 "password - unable to get new password");
84 return retval;
85 }
86
87 retval = pam_get_user(pamh, &user, NULL);
88 if (retval != PAM_SUCCESS) {
89 return retval;
90 }
91
92 struct group *grp;
93 int spec_grp_usr = 0;
94 // Verify whether the user belongs to special group.
95 grp = pam_modutil_getgrnam(pamh, spec_grp_name);
96 if (grp != NULL) {
97 while (*(grp->gr_mem) != NULL) {
98 if (strcmp(user, *grp->gr_mem) == 0) {
99 spec_grp_usr = 1;
100 break;
101 }
102 (grp->gr_mem)++;
103 }
104 }
105
106 if (spec_grp_usr) {
107 // verify the new password is acceptable.
Jiaqing Zhaoa80864a2022-04-04 16:36:35 +0800108 size_t pass_len = strlen(pass_new);
109 size_t user_len = strlen(user);
Patrick Williams9e7627a2023-05-10 07:51:06 -0500110 if (pass_len > MAX_SPEC_GRP_PASS_LENGTH ||
111 user_len > MAX_SPEC_GRP_USER_LENGTH) {
112 pam_syslog(pamh, LOG_ERR,
113 "Password length (%zu) / User name length "
114 "(%zu) is not acceptable for IPMI",
115 pass_len, user_len);
116 pam_error(pamh,
117 "Username %zu / Password %zu exceeds IPMI "
118 "16/20 limit",
119 user_len, pass_len);
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +0530120 pass_new = pass_old = NULL;
Jiaqing Zhaoe3771e82022-04-02 18:02:25 +0800121 return PAM_AUTHTOK_ERR;
Richard Marian Thomaiyar216f2132018-06-12 19:20:48 +0530122 }
123 }
124
125 return PAM_SUCCESS;
126}
127
128/* end of module definition */