int check_sacl(const char *inUser) { #if OSX_SACL int mbrErr = ENOENT; int isMember = 0; uuid_t user_uuid; uuid_t uu; mbrErr = mbr_uid_to_uuid(geteuid(), uu); if (0 == mbrErr) { mbrErr = mbr_check_service_membership(uu, "qtss", &isMember); if (ENOENT == mbrErr) //no acl exists so allow any user. return kSACLAnyUser; } if( (mbrErr = mbr_user_name_to_uuid(inUser, user_uuid)) != 0) { return kSACLUnknownUser; } if((mbrErr = mbr_check_service_membership(user_uuid, "qtss", &isMember)) != 0) { if(mbrErr == ENOENT){ // no ACL exists return kSACLAuthorized; } else { return kSACLNotAuthorized; } } if(isMember == kSACLAuthorized) { return kSACLAuthorized; } return kSACLNotAuthorized; #else return kSACLAuthorized; #endif }
int sacl_check(const char *inUserID) { int err, result; uuid_t guid; if (POSTFIX_SACL_START_ENABLED()) POSTFIX_SACL_START((char *) inUserID); if (var_use_sacl_cache) { /* look up in cache */ result = SACL_CHECK_STATUS_UNKNOWN; switch (sacl_cache_clnt_get(inUserID, &result)) { case SACL_CACHE_STAT_OK: if (result == SACL_CHECK_STATUS_AUTHORIZED) { if (POSTFIX_SACL_CACHED_ENABLED()) POSTFIX_SACL_CACHED((char *) inUserID, 1); return 1; } else if (result == SACL_CHECK_STATUS_UNAUTHORIZED) { if (POSTFIX_SACL_CACHED_ENABLED()) POSTFIX_SACL_CACHED((char *) inUserID, 0); return 0; } else if (result == SACL_CHECK_STATUS_NO_SACL) { if (POSTFIX_SACL_CACHED_ENABLED()) POSTFIX_SACL_CACHED((char *) inUserID, -1); return 1; } break; case SACL_CACHE_STAT_BAD: msg_warn("sacl_check: %s protocol error", var_sacl_cache_service); break; case SACL_CACHE_STAT_FAIL: msg_warn("sacl_check: %s service failure", var_sacl_cache_service); break; } } /* cache miss; perform SACL check */ err = mbr_user_name_to_uuid(inUserID, guid); if (err) { if (POSTFIX_SACL_RESOLVE_ENABLED()) POSTFIX_SACL_RESOLVE((char *) inUserID, 0); if ( msg_verbose ) msg_info("sacl_check: mbr_user_name_to_uuid(%s) failed: %s", inUserID, strerror(err)); return( -1 ); } if (POSTFIX_SACL_RESOLVE_ENABLED()) POSTFIX_SACL_RESOLVE((char *) inUserID, 1); result = 0; err = mbr_check_service_membership(guid, "mail", &result); if (err) { if (POSTFIX_SACL_FINISH_ENABLED()) POSTFIX_SACL_FINISH((char *) inUserID, -1); if (err != ENOENT) { msg_error("sacl_check: mbr_check_service_membership(%s, mail) failed: %s", inUserID, strerror(err)); return -1; } if (var_use_sacl_cache) { /* mail SACL is off. tell cache */ (void) sacl_cache_clnt_no_sacl(); } return 1; } if (POSTFIX_SACL_FINISH_ENABLED()) POSTFIX_SACL_FINISH((char *) inUserID, result); if (var_use_sacl_cache) { /* update cache */ switch (sacl_cache_clnt_put(inUserID, result ? SACL_CHECK_STATUS_AUTHORIZED : SACL_CHECK_STATUS_UNAUTHORIZED)) { case SACL_CACHE_STAT_OK: break; case SACL_CACHE_STAT_BAD: msg_warn("sacl_check: %s protocol error", var_sacl_cache_service); break; case SACL_CACHE_STAT_FAIL: msg_warn("sacl_check: %s service failure", var_sacl_cache_service); break; } } return result; } /* sacl_check */
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, int argc, const char ** argv) { const char * service = NULL; const char * username = NULL; const char * debug = NULL; bool allow_trustacct = false; struct passwd *pwd = NULL; struct passwd pwdbuf; char pwbuffer[2 * PATH_MAX]; uuid_t user_uuid; int err; int ismember; service = openpam_get_option(pamh, "sacl_service"); allow_trustacct = openpam_get_option(pamh, "allow_trustacct"); debug = openpam_get_option(pamh, "debug"); if (!service) { DEBUG_MESSAGE("%s: missing service option", MODULE_NAME); return PAM_IGNORE; } if (pam_get_user(pamh, &username, NULL) != PAM_SUCCESS || username == NULL || *username == '\0') { DEBUG_MESSAGE("%s: missing username", MODULE_NAME); return PAM_SYSTEM_ERR; } DEBUG_MESSAGE("%s: checking if account '%s' can access service '%s'", MODULE_NAME, username, service); /* Since computer trust accounts in OD are not user accounts, you can't * add them to a SACL, so we always let them through (if the option is * set). A computer trust account has a username ending in '$' and no * corresponding user account (ie. no passwd entry). */ if (allow_trustacct) { const char * c; c = strrchr(username, '$'); if (c && *(c + 1) == '\0' && getpwnam_r(username, &pwdbuf, pwbuffer, sizeof(pwbuffer), &pwd) == 0) { DEBUG_MESSAGE("%s: allowing '%s' because it is a " "computer trust account", MODULE_NAME, username); return PAM_SUCCESS; } } /* Get the UUID. This will fail if the user is is logging in over * SMB, is specifed as DOMAIN\user or user@REALM and the directory * does not have the aliases we need. */ if (mbr_user_name_to_uuid(username, user_uuid)) { char * sacl_group; /* We couldn't map the user to a UID, but we only care about * this if the relevant SACL groups exist. */ if (asprintf(&sacl_group, "com.apple.access_%s\n", service) == -1) { return PAM_SYSTEM_ERR; } if (getgrnam(sacl_group) == NULL && getgrnam("com.apple.access_all_services") == NULL) { DEBUG_MESSAGE("%s: allowing '%s' " "due to absence of service ACL", MODULE_NAME, username); free(sacl_group); return PAM_SUCCESS; } DEBUG_MESSAGE("%s: denying '%s' due to missing UUID", MODULE_NAME, username); free(sacl_group); return PAM_PERM_DENIED; } err = mbr_check_service_membership(user_uuid, service, &ismember); if (err) { if (err == ENOENT) { /* Service ACLs not configured. */ DEBUG_MESSAGE("%s: allowing '%s' " "due to unconfigured service ACLs", MODULE_NAME, username); return PAM_SUCCESS; } DEBUG_MESSAGE("%s: denying '%s' " "due to failed service ACL check (errno=%d)", MODULE_NAME, username, err); return PAM_PERM_DENIED; } if (ismember) { DEBUG_MESSAGE("%s: allowing '%s'", MODULE_NAME, username); return PAM_SUCCESS; } else { DEBUG_MESSAGE("%s: denying '%s' " "due to failed service ACL check", MODULE_NAME, username); return PAM_PERM_DENIED; } }
int main (int argc, char * const argv[]) { char *searchType; char *groupOrServiceName; if ( argc == 4 ) { searchType = argv[2]; groupOrServiceName = argv[3]; } else if ( argc == 3 ) { searchType = "-s"; groupOrServiceName = argv[2]; } else { printUsage("Wrong number of arguments."); return 1; } uuid_t user; int result = mbr_user_name_to_uuid(argv[1], user); int isMember = 0; if ( result != 0 ) { printf("Invalid user\n"); return 1; } if ( strncmp(searchType, "-s", 2) == 0 ) { result = mbr_check_service_membership(user, groupOrServiceName, &isMember); if ( ( isMember == 1 ) || ( result == 2 ) ) { printf("Member (%i, %i)\n", isMember, result); return 0; } else { printf("Not a member (%i, %i)\n", isMember, result); return 1; } } else if ( strncmp(searchType, "-g", 2) == 0 ) { uuid_t group; result = mbr_group_name_to_uuid(groupOrServiceName, group); if ( result != 0 ) { printf("Invalid group\n"); return 1; } result = mbr_check_membership(user, group, &isMember); if ( ( result == 0 ) && ( isMember == 1 ) ) { printf("Member (%i, %i)\n", isMember, result); return 0; } else { printf("Not a member (%i, %i)", isMember, result); return 1; } } else { printUsage("Use -g to search for groups, or -s to search for a service."); return 1; } }