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 }
//---------------------------------------------------------------------- // dsaccess_authorize_user //---------------------------------------------------------------------- static int dsaccess_authorize_user(u_char* name, int len) { tDirReference dirRef; tDirStatus dsResult = eDSNoErr; int authorized = 0; tDirNodeReference searchNodeRef; tAttributeValueEntryPtr gUID; UInt32 searchNodeCount; char* user_name; uuid_t userid; int result; int ismember; if (len < 1) { error("DSAccessControl plugin: invalid user name has zero length\n"); return 0; } if ((user_name = (char*)malloc(len + 1)) == 0) { error("DSAccessControl plugin: unable to allocate memory for user name\n"); return 0; } bcopy(name, user_name, len); *(user_name + len) = 0; if ((dsResult = dsOpenDirService(&dirRef)) == eDSNoErr) { // get the search node ref if ((dsResult = dsauth_get_search_node_ref(dirRef, 1, &searchNodeRef, &searchNodeCount)) == eDSNoErr) { // get the user's generated user Id if ((dsResult = dsauth_get_user_attr(dirRef, searchNodeRef, user_name, kDS1AttrGeneratedUID, &gUID)) == eDSNoErr) { if (gUID != 0) { if (!mbr_string_to_uuid(gUID->fAttributeValueData.fBufferData, userid)) { // check if user is member authorized result = mbr_check_service_membership(userid, VPN_SERVICE_NAME, &ismember); if (result == ENOENT || (result == 0 && ismember != 0)) authorized = 1; } dsDeallocAttributeValueEntry(dirRef, gUID); } } dsCloseDirNode(searchNodeRef); // close the search node } dsCloseDirService(dirRef); } if (authorized) notice("DSAccessControl plugin: User '%s' authorized for access\n", user_name); else notice("DSAccessControl plugin: User '%s' not authorized for access\n", user_name); free(user_name); return authorized; }
/* * member of the radius group? */ static rlm_rcode_t mod_authorize(UNUSED void *instance, REQUEST *request) { struct passwd *userdata = NULL; struct group *groupdata = NULL; int ismember = 0; RADCLIENT *rad_client = NULL; uuid_t uuid; uuid_t guid_sacl; uuid_t guid_nasgroup; int err; char host_ipaddr[128] = {0}; if (!request || !request->username) { RDEBUG("OpenDirectory requires a User-Name attribute."); return RLM_MODULE_NOOP; } /* resolve SACL */ uuid_clear(guid_sacl); groupdata = getgrnam(kRadiusSACLName); if (groupdata != NULL) { err = mbr_gid_to_uuid(groupdata->gr_gid, guid_sacl); if (err != 0) { ERROR("rlm_opendirectory: The group \"%s\" does not have a GUID.", kRadiusSACLName); return RLM_MODULE_FAIL; } } else { RDEBUG("The SACL group \"%s\" does not exist on this system.", kRadiusSACLName); } /* resolve client access list */ uuid_clear(guid_nasgroup); rad_client = request->client; #if 0 if (rad_client->community[0] != '\0' ) { /* * The "community" can be a GUID (Globally Unique ID) or * a group name */ if (uuid_parse(rad_client->community, guid_nasgroup) != 0) { /* attempt to resolve the name */ groupdata = getgrnam(rad_client->community); if (!groupdata) { AUTH("rlm_opendirectory: The group \"%s\" does not exist on this system.", rad_client->community); return RLM_MODULE_FAIL; } err = mbr_gid_to_uuid(groupdata->gr_gid, guid_nasgroup); if (err != 0) { AUTH("rlm_opendirectory: The group \"%s\" does not have a GUID.", rad_client->community); return RLM_MODULE_FAIL; } } } else #endif { if (!rad_client) { RDEBUG("The client record could not be found for host %s.", ip_ntoh(&request->packet->src_ipaddr, host_ipaddr, sizeof(host_ipaddr))); } else { RDEBUG("The host %s does not have an access group.", ip_ntoh(&request->packet->src_ipaddr, host_ipaddr, sizeof(host_ipaddr))); } } if (uuid_is_null(guid_sacl) && uuid_is_null(guid_nasgroup)) { RDEBUG("no access control groups, all users allowed."); if (pairfind(request->config_items, PW_AUTH_TYPE, 0, TAG_ANY) == NULL) { pairmake_config("Auth-Type", kAuthType, T_OP_EQ); RDEBUG("Setting Auth-Type = %s", kAuthType); } return RLM_MODULE_OK; } /* resolve user */ uuid_clear(uuid); userdata = getpwnam(request->username->vp_strvalue); if (userdata != NULL) { err = mbr_uid_to_uuid(userdata->pw_uid, uuid); if (err != 0) uuid_clear(uuid); } if (uuid_is_null(uuid)) { REDEBUG("Could not get the user's uuid", T_OP_EQ); return RLM_MODULE_NOTFOUND; } if (!uuid_is_null(guid_sacl)) { err = mbr_check_service_membership(uuid, kRadiusServiceName, &ismember); if (err != 0) { REDEBUG("Failed to check group membership", T_OP_EQ); return RLM_MODULE_FAIL; } if (ismember == 0) { REDEBUG("User is not authorized", T_OP_EQ); return RLM_MODULE_USERLOCK; } } if (!uuid_is_null(guid_nasgroup)) { err = mbr_check_membership_refresh(uuid, guid_nasgroup, &ismember); if (err != 0) { REDEBUG("Failed to check group membership", T_OP_EQ); return RLM_MODULE_FAIL; } if (ismember == 0) { REDEBUG("User is not authorized", T_OP_EQ); return RLM_MODULE_USERLOCK; } } if (pairfind(request->config_items, PW_AUTH_TYPE, 0, TAG_ANY) == NULL) { pairmake_config("Auth-Type", kAuthType, T_OP_EQ); RDEBUG("Setting Auth-Type = %s", kAuthType); } return RLM_MODULE_OK; }
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; } }