/* // Copyright (c) 2018 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ #include #include #include #include #include #include #include #include #define MAX_SPEC_GRP_PASS_LENGTH 20 #define MAX_SPEC_GRP_USER_LENGTH 16 /* * This module is intended to verify special group user password matches the * restrictions needed. * * Note: Other than for pam_chauthtok(), pam_ipmicheck module should not be * used for other purpose like authentication, session & account management. * This module has to be used along with pam_ipmisave module, which will save * the passwords of the special group users. */ static const char *get_option(const char *option, int argc, const char **argv) { int i = 0; size_t len = strlen(option); for (i = 0; i < argc; ++i) { if (strncmp(option, argv[i], len) == 0) { if (argv[i][len] == '=') { return &argv[i][len + 1]; } } } return NULL; } /* Password Management API's */ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) { int retval = -1; const char *user = NULL; const char *pass_new = NULL, *pass_old = NULL; const char *spec_grp_name = get_option("spec_grp_name", argc, argv); if (spec_grp_name == NULL) { return PAM_IGNORE; } pam_syslog(pamh, LOG_DEBUG, "Special group name is %s", spec_grp_name); if (flags & PAM_PRELIM_CHECK) { // send success to verify other stacked modules prelim check. pam_syslog(pamh, LOG_DEBUG, "PRELIM_CHECK Called"); return PAM_SUCCESS; } // Read new password. // Note: Subsequent modules must use stacked password option use_authtok retval = pam_get_authtok(pamh, PAM_AUTHTOK, &pass_new, NULL); if (retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "password - unable to get new password"); return retval; } retval = pam_get_user(pamh, &user, NULL); if (retval != PAM_SUCCESS) { return retval; } struct group *grp; int spec_grp_usr = 0; // Verify whether the user belongs to special group. grp = pam_modutil_getgrnam(pamh, spec_grp_name); if (grp != NULL) { while (*(grp->gr_mem) != NULL) { if (strcmp(user, *grp->gr_mem) == 0) { spec_grp_usr = 1; break; } (grp->gr_mem)++; } } if (spec_grp_usr) { // verify the new password is acceptable. size_t pass_len = strlen(pass_new); size_t user_len = strlen(user); if (pass_len > MAX_SPEC_GRP_PASS_LENGTH || user_len > MAX_SPEC_GRP_USER_LENGTH) { pam_syslog(pamh, LOG_ERR, "Password length (%zu) / User name length " "(%zu) is not acceptable for IPMI", pass_len, user_len); pam_error(pamh, "Username %zu / Password %zu exceeds IPMI " "16/20 limit", user_len, pass_len); pass_new = pass_old = NULL; return PAM_AUTHTOK_ERR; } } return PAM_SUCCESS; } /* end of module definition */