blob: 41b3abf2da9c3fa4b402d31a688071146fa9129e [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
17#include <syslog.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdarg.h>
21#include <string.h>
22
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
30
31/*
32 * This module is intended to verify special group user password matches the
33 * restrictions needed.
34 *
35 * Note: Other than for pam_chauthtok(), pam_ipmicheck module should not be
36 * used for other purpose like authentication, session & account management.
37 * This module has to be used along with pam_ipmisave module, which will save
38 * the passwords of the special group users.
39 */
40
41
42static const char *get_option(const pam_handle_t *pamh, const char *option,
43 int argc, const char **argv)
44{
45 int i = 0;
46 size_t len = strlen(option);
47
48 for (i = 0; i < argc; ++i) {
49 if (strncmp(option, argv[i], len) == 0) {
50 if (argv[i][len] == '=') {
51 return &argv[i][len + 1];
52 }
53 }
54 }
55 return NULL;
56}
57
58/* Password Management API's */
59
60int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
61{
62 int retval = -1;
63 const void *item = NULL;
64 const char *user = NULL;
65 const char *pass_new = NULL, *pass_old = NULL;
66 const char *spec_grp_name =
67 get_option(pamh, "spec_grp_name", argc, argv);
68
69 pam_syslog(pamh, LOG_DEBUG, "Special group name is %s", spec_grp_name);
70
71 if (spec_grp_name == NULL) {
72 return PAM_IGNORE;
73 }
74 if (flags & PAM_PRELIM_CHECK) {
75 // send success to verify other stacked modules prelim check.
76 pam_syslog(pamh, LOG_DEBUG, "PRELIM_CHECK Called");
77 return PAM_SUCCESS;
78 }
79
80 // Read new password.
81 // Note: Subsequent modules must use stacked password option use_authtok
82 retval = pam_get_authtok(pamh, PAM_AUTHTOK, &pass_new, NULL);
83 if (retval != PAM_SUCCESS) {
84 pam_syslog(pamh, LOG_ERR,
85 "password - unable to get new password");
86 return retval;
87 }
88
89 retval = pam_get_user(pamh, &user, NULL);
90 if (retval != PAM_SUCCESS) {
91 return retval;
92 }
93
94 struct group *grp;
95 int spec_grp_usr = 0;
96 // Verify whether the user belongs to special group.
97 grp = pam_modutil_getgrnam(pamh, spec_grp_name);
98 if (grp != NULL) {
99 while (*(grp->gr_mem) != NULL) {
100 if (strcmp(user, *grp->gr_mem) == 0) {
101 spec_grp_usr = 1;
102 break;
103 }
104 (grp->gr_mem)++;
105 }
106 }
107
108 if (spec_grp_usr) {
109 // verify the new password is acceptable.
110 if (strlen(pass_new) > MAX_SPEC_GRP_PASS_LENGTH
111 || strlen(user) > MAX_SPEC_GRP_USER_LENGTH) {
112 pam_syslog(
113 pamh, LOG_ERR,
114 "Password length (%x) / User name length (%x) not acceptable",
115 strlen(pass_new), strlen(user));
116 pass_new = pass_old = NULL;
117 return PAM_NEW_AUTHTOK_REQD;
118 }
119 }
120
121 return PAM_SUCCESS;
122}
123
124/* end of module definition */