// Initialize all structures that will be used in benchmark()
// 1. make local or network node for OD query
// 2. create user key 
int
benchmark_initworker(void *tsd)
{
    CFErrorRef    error;
    tsd_t *ts = (tsd_t *)tsd;

    debug("benchmark_initworker: %s", (optNodeLocal) ? "local" : "network");


    // create OD node for local or OD query
    if (optNodeLocal) {
        ts->node = ODNodeCreateWithNodeType(NULL, kODSessionDefault, kODNodeTypeLocalNodes, &error);
    }
    else {
        CFStringRef nodenameStr = CFStringCreateWithCString(kCFAllocatorDefault, nodename, kCFStringEncodingUTF8);
        ts->node = ODNodeCreateWithName(NULL, kODSessionDefault, nodenameStr, &error);
        CFRelease(nodenameStr);
    }

    if (!ts->node) {
        debug("error calling ODNodeCreateWithNodeType\n");
        exit(1);
    }

    CFRetain (ts->node);

    debug("benchmark_initworker: ODNodeRef = 0x%lx\n", ts->node);
    return (0);
}
Exemplo n.º 2
0
Boolean
AFPUserList_init(AFPUserListRef users)
{
    CFErrorRef	error;
    int		i;
    int		n;
    CFArrayRef	results;
    ODQueryRef	query;

    bzero(users, sizeof(*users));

    users->node = ODNodeCreateWithNodeType(NULL, kODSessionDefault, 
					   kODNodeTypeLocalNodes, &error);
    if (users->node == NULL) {
	my_log(LOG_NOTICE,
	       "AFPUserList_init: ODNodeCreateWithNodeType() failed");
	goto failed;
    }

    query = ODQueryCreateWithNode(NULL,
				  users->node,			// inNode
				  CFSTR(kDSStdRecordTypeUsers),	// inRecordTypeOrList
				  CFSTR(NIPROP__CREATOR),	// inAttribute
				  kODMatchEqualTo,		// inMatchType
				  CFSTR(BSDPD_CREATOR),		// inQueryValueOrList
				  CFSTR(kDSAttributesAll),	// inReturnAttributeOrList
				  0,				// inMaxResults
				  &error);
    if (query == NULL) {
	my_log(LOG_NOTICE, "AFPUserList_init: ODQueryCreateWithNode() failed");
	my_CFRelease(&error);
	goto failed;
    }

    results = ODQueryCopyResults(query, FALSE, &error);
    CFRelease(query);
    if (results == NULL) {
	my_log(LOG_NOTICE, "AFPUserList_init: ODQueryCopyResults() failed");
	my_CFRelease(&error);
	goto failed;
    }

    users->list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
    n = CFArrayGetCount(results);
    for (i = 0; i < n; i++) {
	ODRecordRef		record;
	AFPUserRef		user;

	record = (ODRecordRef)CFArrayGetValueAtIndex(results, i);
	user = AFPUser_create(record);
	CFArrayAppendValue(users->list, user);
	CFRelease(user);
    }
    CFRelease(results);
    return (TRUE);

 failed:
    AFPUserList_free(users);
    return (FALSE);
}
Exemplo n.º 3
0
int
odkerb_configure_search_node(void)
{
    int retval = -1;
    CFErrorRef cfError = NULL;

    if (gSearchNode != NULL) {
        if (ODNodeGetName(gSearchNode) == NULL) {
            ODKERB_LOG(LOG_DEBUG, "Flushing search node");
            CF_SAFE_RELEASE(gSearchNode);
            gSearchNode = NULL;
        }
    }
    
    if (gSearchNode == NULL) {
        gSearchNode = ODNodeCreateWithNodeType(kCFAllocatorDefault, kODSessionDefault,
                                               kODNodeTypeAuthentication, &cfError);
        if (gSearchNode == NULL || cfError != NULL) {
            ODKERB_LOG_CFERROR(LOG_INFO, "Unable to get a reference to the search node", cfError);
            goto failure;
        }
    }

    retval = 0;
failure:
    CF_SAFE_RELEASE(cfError);
    return retval;
}
Exemplo n.º 4
0
/*
 * Fetch all the map records in Open Directory that have a certain attribute
 * that matches a certain value and pass those records to a callback function.
 */
static int
od_search(CFStringRef attr_to_match, char *value_to_match, callback_fn callback,
    void *udata)
{
	int ret;
	CFErrorRef error;
	char *errstring;
	ODNodeRef node_ref;
	CFArrayRef attrs;
	CFStringRef value_to_match_cfstr;
	ODQueryRef query_ref;
	CFArrayRef results;
	CFIndex num_results;
	CFIndex i;
	ODRecordRef record;
	callback_ret_t callback_ret;

	/*
	 * Create the search node.
	 */
	error = NULL;
	node_ref = ODNodeCreateWithNodeType(kCFAllocatorDefault, kODSessionDefault, 
	     kODNodeTypeAuthentication, &error);
	if (node_ref == NULL) {
		errstring = od_get_error_string(error);
		pr_msg("od_search: can't create search node for /Search: %s",
		    errstring);
		free(errstring);
		return (__NSW_UNAVAIL);
	}

	/*
	 * Create the query.
	 */
	value_to_match_cfstr = CFStringCreateWithCString(kCFAllocatorDefault,
	    value_to_match, kCFStringEncodingUTF8);
	if (value_to_match_cfstr == NULL) {
		CFRelease(node_ref);
		pr_msg("od_search: can't make CFString from %s",
		    value_to_match);
		return (__NSW_UNAVAIL);
	}
	attrs = CFArrayCreate(kCFAllocatorDefault,
	    (const void *[2]){kODAttributeTypeRecordName,
	                      kODAttributeTypeAutomountInformation}, 2,
Exemplo n.º 5
0
/* ------------------------------------------------------------------
 *	aod_get_user_options ()
 */
int aod_get_user_options ( const char *inUserID, struct od_user_opts *in_out_opts )
{
	assert((inUserID != NULL) && (in_out_opts != NULL));

	memset( in_out_opts, 0, sizeof( struct od_user_opts ) );
	in_out_opts->fAcctState = eUnknownAcctState;

	if ( POSTFIX_OD_LOOKUP_START_ENABLED() )
		POSTFIX_OD_LOOKUP_START((char *) inUserID, in_out_opts);

	/* create default session */
	CFErrorRef cf_err_ref = NULL;
	ODSessionRef od_session_ref = ODSessionCreate( kCFAllocatorDefault, NULL, &cf_err_ref );
	if ( !od_session_ref ) {
		/* print the error and bail */
		print_cf_error( cf_err_ref, inUserID, "Unable to create OD Session" );
		return( -1 );
	}

	/* get seach node */
	ODNodeRef od_node_ref = ODNodeCreateWithNodeType( kCFAllocatorDefault, od_session_ref, kODNodeTypeAuthentication, &cf_err_ref );
	if ( !od_node_ref ) {
		/* print the error and bail */
		print_cf_error( cf_err_ref, inUserID, "Unable to create OD Node Reference" );

		/* release OD session */
		CFRelease( od_session_ref );
		return( -1 );
	}

	/* get account state and auto-forward address, if any */
	int out_status = get_user_attributes( od_node_ref, inUserID, in_out_opts );

	CFRelease( od_node_ref );
	CFRelease( od_session_ref );

	if ( POSTFIX_OD_LOOKUP_FINISH_ENABLED() )
		POSTFIX_OD_LOOKUP_FINISH((char *) inUserID, in_out_opts, out_status);

	return( out_status );
} /* aod_get_user_options */
Exemplo n.º 6
0
int main(int argc, char *argv[])
{
    int				ch;
	char		   *operation		= nil;
	bool			bReadOption		= false;
	bool			bCreateOption   = false;
	bool			bDeleteOption   = false;
	bool			bEditOption		= false;
	bool			bInteractivePwd = false;
	bool			bNoVerify		= false;
	bool			bVerbose		= false;
	bool			bCheckMemberOption	= false;
	char		   *nodename		= nil;
	char		   *username		= nil;
	bool			bDefaultUser	= false;
	bool			bCompList		= false;
	char		   *password		= nil;
	char		   *addrecordname   = nil;
	char		   *delrecordname   = nil;
	char		   *recordtype		= nil;
	char		   *gid				= nil;
	char		   *guid			= nil;
	char		   *smbSID			= nil;
	char		   *realname		= nil;
	char		   *keyword			= nil;
	char		   *comment			= nil;
	char		   *timeToLive		= nil;
	char		   *groupname		= nil;
	char		   *member			= nil;
	char		   *format			= nil;	//be either "l" for legacy or "n" for new group format
	const char	   *grouptype		= NULL;
	int				exitcode		= 0;
	uuid_t			uuid;
    
	ODNodeRef			aDSNodeRef		= NULL;
	ODNodeRef			aDSSearchRef	= NULL;
	bool				bContinueAdd	= false;
	char			   *groupRecordName	= nil;
	__block ODRecordRef	aGroupRecRef	= NULL;
	__block ODRecordRef	aGroupRecRef2	= NULL;
	CFErrorRef			aErrorRef		= NULL;
	char				*errorTok		= NULL;

	if (argc < 2)
	{
		usage();
		exit(0);
	}
	
	if ( strcmp(argv[1], "-appleversion") == 0 )
        dsToolAppleVersionExit( argv[0] );
	
    while ((ch = getopt(argc, argv, "LT:o:pqvn:m:u:P:a:d:t:i:g:r:k:c:s:S:f:?h")) != -1) {
        switch (ch) {
            case 'o':
                operation = strdup(optarg);
                if (operation != nil)
                {
                    if ( strcasecmp(operation, "read") == 0 )
                    {
                        bReadOption = true;
                    }
                    else if ( strcasecmp(operation, "create") == 0 )
                    {
                        bCreateOption = true;
                    }
                    else if ( strcasecmp(operation, "delete") == 0 )
                    {
                        bDeleteOption = true;
                    }
                    else if ( strcasecmp(operation, "edit") == 0 )
                    {
                        bEditOption = true;
                    }
                    else if ( strcasecmp(operation, "checkmember") == 0 )
                    {
                        bCheckMemberOption = true;
                    }
                }
				break;
            case 'p':
                bInteractivePwd = true;
                break;
            case 'q':
                bNoVerify = true;
                break;
            case 'v':
                bVerbose = true;
                break;
            case 'm':
                member = strdup(optarg);
                break;
            case 'n':
                nodename = strdup(optarg);
                break;
            case 'u':
                username = strdup(optarg);
                break;
            case 'P':
                password = strdup(optarg);
                break;
            case 'a':
                addrecordname = strdup(optarg);
                break;
            case 'd':
                delrecordname = strdup(optarg);
                break;
            case 't':
                recordtype = strdup(optarg);
                break;
			case 'T':
				grouptype = optarg;
				break;
			case 'L':
				bCompList = true;
				break;
            case 'i':
				strtol( optarg, &errorTok, 10 );
				if ( errorTok == NULL || errorTok[0] == '\0' ) {
					gid = strdup(optarg);
				}
				else {
					printf( "GID contains non-numeric characters\n" );
					return EX_USAGE;
				}
                break;
            case 'g':
				uuid_clear( uuid );
				
				// don't allow malformed UUIDs nor an empty one
				if ( uuid_parse(optarg, uuid) == 0 && uuid_is_null(uuid) == false ) {
					guid = strdup(optarg);
				}
				else {
					printf( "GUID provided is not a valid UUID\n" );
					return EX_USAGE;
				}
                break;
            case 'r':
                realname = strdup(optarg);
                break;
            case 'k':
                keyword = strdup(optarg);
                break;
            case 'c':
                comment = strdup(optarg);
                break;
            case 's':
                timeToLive = strdup(optarg);
                break;
            case 'S':
                smbSID = strdup(optarg);
                break;
            case 'f':
                format = strdup(optarg);
                break;
            case '?':
            case 'h':
            default:
			{
				usage();
				return EX_USAGE;
			}
        }
    }
	
	argc -= optind;
	argv += optind;
	
	if (argc == 0)
	{
		printErrorOrMessage( NULL, "No group name provided", bVerbose );
		return EX_USAGE;
	}
	
	groupname = strdup( argv[0] );
	
	if (!bCreateOption && !bDeleteOption && !bEditOption && !bCheckMemberOption)
	{
		bReadOption = true; //default option
	}
	
	if (username == nil)
	{
		struct passwd* pw = NULL;
		pw = getpwuid(getuid());
		if (pw != NULL && pw->pw_name != NULL && pw->pw_name[0] != '\0')
		{
			username = strdup(pw->pw_name);
		}
		else
		{
			printf("***Username <-u username> must be explicitly provided in this shell***\n");
			usage();
			exit(0);
		}
		bDefaultUser = true;
	}
    
	if (bVerbose)
	{
		printf("dseditgroup verbose mode\n");
		printf("Options selected by user:\n");
		if (bReadOption)
			printf("Read option selected\n");
		if (bCreateOption)
			printf("Create option selected\n");
		if (bDeleteOption)
			printf("Delete option selected\n");
		if (bEditOption)
			printf("Edit option selected\n");
		if (bCheckMemberOption)
			printf("Checking membership selected\n");
		if (bInteractivePwd)
			printf("Interactive password option selected\n");
		if (bNoVerify)
			printf("User verification is disabled\n");
		if (nodename)
			printf("Nodename provided as <%s>\n", nodename);
		if (username && !bDefaultUser)
			printf("Username provided as <%s>\n", username);
		else
			printf("Username determined to be <%s>\n", username);
		if ( password && !bInteractivePwd )
			printf("Password provided as <%s>\n", password);
		if (addrecordname)
			printf("Recordname to be added provided as <%s>\n", addrecordname);
		if (delrecordname)
			printf("Recordname to be deleted provided as <%s>\n", delrecordname);
		if (recordtype)
			printf("Recordtype provided as <%s>\n", recordtype);
		if (grouptype)
			printf("Grouptype provided as <%s>\n", grouptype);
		if (gid)
			printf("GID provided as <%s>\n", gid);
		if (guid)
			printf("GUID provided as <%s>\n", guid);
		if (smbSID)
			printf("SID provided as <%s>\n", smbSID);
		if (realname)
			printf("Realname provided as <%s>\n", realname);
		if (keyword)
			printf("Keyword provided as <%s>\n", keyword);
		if (comment)
			printf("Comment provided as <%s>\n", comment);
		if (timeToLive)
			printf("TimeToLive provided as <%s>\n", timeToLive);
		if (groupname)
			printf("Groupname provided as <%s>\n", groupname);
		if (bCompList)
			printf("Will maintain computer lists when applicable\n" );
		printf("\n");
	}
	
	ODRecordType (^mapRecTypeWithDefault)(const char *, ODRecordType) = ^(const char *inType, ODRecordType inDefault) {
		if ( inType != NULL )
		{
			if ( strcasecmp(inType, "user") == 0) {
				return kODRecordTypeUsers;
			}
			else if ( strcasecmp(inType, "group") == 0) {
				return kODRecordTypeGroups;
			}
			else if ( strcasecmp(inType, "computer") == 0) {
				return kODRecordTypeComputers;
			}
			else if ( strcasecmp(inType, "computergroup") == 0 ) {
				return kODRecordTypeComputerGroups;
			}
		}
		
		return inDefault;
	};
    
	if (bCheckMemberOption == false &&
		bReadOption == false &&
		(!bNoVerify && ( !bDefaultUser && ( (password == nil) || bInteractivePwd ) ) || (bDefaultUser && bInteractivePwd)) )
	{
		password = read_passphrase("Please enter user password:"******"." we default to the local node by passing nil as the node name to getNodeRef
			aDSNodeRef = aLocalNodeRef;
			bIsLocalNode = true;
        }
		else
		{
            // otherwise we pass the provided nodename to getNodeRef
			CFStringRef cfNodeName = CFStringCreateWithCString( kCFAllocatorDefault, nodename, kCFStringEncodingUTF8 );
			if ( cfNodeName != NULL ) {
				aDSNodeRef = ODNodeCreateWithName( kCFAllocatorDefault, kODSessionDefault, cfNodeName, &aErrorRef );
				CFRelease( cfNodeName );
				if (aDSNodeRef == NULL) {
					exitcode = printErrorOrMessage(NULL, "Error locating specified node.", bVerbose);
					break;
				}
				
				if ( CFEqual(ODNodeGetName(aDSNodeRef), ODNodeGetName(aLocalNodeRef)) == true ) {
					bIsLocalNode = true;
				}
			}
			else {
				exitcode = printErrorOrMessage( NULL, "Error parsing node name.", bVerbose );
				break;
			}
        }
		
		if ( aDSNodeRef == NULL ) {
			exitcode = printErrorOrMessage( &aErrorRef, "getNodeRef failed to obtain a node reference", bVerbose );
			break;
		}
		
		aDSSearchRef = ODNodeCreateWithNodeType( kCFAllocatorDefault, kODSessionDefault, kODNodeTypeAuthentication, &aErrorRef );
		
		CFStringRef groupNameCF = CFStringCreateWithCString( kCFAllocatorDefault, groupname, kCFStringEncodingUTF8 );
		if ( groupNameCF == NULL ) {
			exitcode = EX_SOFTWARE;
			printErrorOrMessage( NULL, "Unable to parse groupname", bVerbose );
			break;
		}
		
		CFArrayRef attribs = CFArrayCreate( kCFAllocatorDefault, (CFTypeRef *) &kODAttributeTypeStandardOnly, 1, &kCFTypeArrayCallBacks );
		if ( attribs == NULL ) {
			exitcode = EX_SOFTWARE;
			printErrorOrMessage( NULL, "Unable to allocate array", bVerbose );
			break;
		}

		ODRecordType grpType = mapRecTypeWithDefault( grouptype, kODRecordTypeGroups );
		
		bool (^isLocalNode)(ODRecordRef record) = ^(ODRecordRef record) {
			CFArrayRef values = ODRecordCopyValues( record, kODAttributeTypeMetaNodeLocation, NULL );
			if ( values != NULL ) {
				
				if ( CFArrayGetCount(values) > 0 && CFEqual(CFArrayGetValueAtIndex(values, 0), ODNodeGetName(aLocalNodeRef)) == true ) {
					return (bool) true;
				}
				
				CFRelease( values );
			}
			
			return (bool) false;
		};
		
		aGroupRecRef = ODNodeCopyRecord( aDSNodeRef, grpType, groupNameCF, attribs, NULL );
		if ( aGroupRecRef != NULL ) {
			bIsLocalNode = isLocalNode( aGroupRecRef );
		}
		
		/* The group must already exist unless -o create is specified. */
		if (aGroupRecRef == NULL && !bCreateOption) {
			exitcode = printErrorOrMessage(NULL, "Group not found.", bVerbose);
			break;
		}

		if ( bCompList == true && grpType == kODRecordTypeComputerGroups )
		{
			aGroupRecRef2 = ODNodeCopyRecord( aDSNodeRef, kODRecordTypeComputerLists, groupNameCF, NULL, NULL );
			if ( aGroupRecRef2 != NULL && isLocalNode(aGroupRecRef2) == true )
			{
				// if we got a group record, let's see if it is also local node
				if ( bIsLocalNode == false && aGroupRecRef != NULL )
				{
					if ( bVerbose == true ) {
						printf( "Skipping Computer list because it's on a different node\n" );
						CFRelease( aGroupRecRef2 );
						aGroupRecRef2 = NULL;
					}
				}
				else {
					bIsLocalNode = true;
				}
			}
		}
		
		if ( geteuid() == 0 && bIsLocalNode == true && (username == NULL || password == NULL) )
		{
			// we are running as root and no password or name provided
			if ( bVerbose == true ) {
				printf( "Skipping authentication because user has effective ID 0\n" );
			}
		}
		else if ( bDeleteOption == true || bCreateOption == true || bEditOption == true )
		{
			// need to auth for changes
			if (username == NULL || password == NULL) {
				exitcode = printErrorOrMessage(NULL, "Username and password must be provided.", bVerbose);
				break;
			}

			bool bSuccess = false;
			CFStringRef user = CFStringCreateWithCString(NULL, username, kCFStringEncodingUTF8);
			CFStringRef pass = CFStringCreateWithCString(NULL, password, kCFStringEncodingUTF8);
			
			/*
			 * aDSNodeRef may be /Search unless we're creating a new group. Fortunately,
			 * we can authenticate with the specific group(s) most of the time. We still
			 * authenticate with the node directly when the specified group doesn't exist.
			 * As noted above, this is only allowed when creating a new group, in which
			 * case aDSNodeRef cannot be /Search.
			 */
			if (aGroupRecRef != NULL) {
				bSuccess = ODRecordSetNodeCredentials(aGroupRecRef, user, pass, &aErrorRef);
				if (aGroupRecRef2 != NULL) {
					ODRecordSetNodeCredentials(aGroupRecRef2, user, pass, &aErrorRef);
				}
			} else {
				bSuccess = ODNodeSetCredentials(aDSNodeRef, NULL, user, pass, &aErrorRef);
			}

			CFRelease(user);
			CFRelease(pass);

			if (!bSuccess) {
				exitcode = printErrorOrMessage(&aErrorRef, "Failed to set credentials.", bVerbose);
				break;
			}
		}
		
		CFErrorRef (^deleteRecords)(void) = ^(void) {
			CFErrorRef error = NULL;
			if ( aGroupRecRef != NULL )
			{
				if ( ODRecordDelete(aGroupRecRef, &error) == false ) {
					return error;
				}
				
				CFRelease( aGroupRecRef );
				aGroupRecRef = NULL;
			}
			
			if ( aGroupRecRef2 != NULL )
			{
				if ( ODRecordDelete(aGroupRecRef2, &error) == false ) {
					return error;
				}
				
				CFRelease( aGroupRecRef2 );
				aGroupRecRef2 = NULL;
			}
			
			return error;
		};
		
		if ( bReadOption == true || bDeleteOption == true )
		{
			if ( aGroupRecRef != NULL || aGroupRecRef2 != NULL )
			{
				if ( bDeleteOption == true && aGroupRecRef != NULL ) {
					printErrorOrMessage( NULL, "Group record below will be deleted:", bVerbose );
				}
				
				CFDictionaryRef cfDetails = ODRecordCopyDetails( aGroupRecRef, NULL, NULL );
				if ( cfDetails != NULL ) {
					CFDictionaryApplyFunction( cfDetails, printDictionary, NULL );
					CFRelease( cfDetails );
				}
				
				if ( bDeleteOption == true && (aErrorRef = deleteRecords()) != NULL ) {
					exitcode = printErrorOrMessage( &aErrorRef, "Unable to delete record", bVerbose );
					break;
				}
			}
			else
			{
				exitcode = printErrorOrMessage( NULL, "Group was not found.", bVerbose );
				break;
			}
		}
		else if (bCreateOption)
		{
			if ( aGroupRecRef != NULL || aGroupRecRef2 != NULL )
			{
				char responseValue[8] = {0};
				if (!bNoVerify)
				{
					printf("Create called on existing record - do you want to overwrite, y or n : ");
					scanf( "%c", responseValue );
					printf("\n");
				}
				
				if (bNoVerify || (responseValue[0] == 'y') || (responseValue[0] == 'Y'))
				{
					if ( (aErrorRef = deleteRecords()) != NULL ) {
						exitcode = printErrorOrMessage( &aErrorRef, "Unable to replace the record", bVerbose );
						break;
					}
				}
				else
				{
					exitcode = EX_CANTCREAT;
					printErrorOrMessage( NULL, "Operation cancelled because record could not be replaced", bVerbose );
					break;
				}
			}
			
			if ( aGroupRecRef == NULL )
			{
				aGroupRecRef = ODNodeCreateRecord( aDSNodeRef, grpType, groupNameCF, NULL, &aErrorRef );
				if ( aGroupRecRef != NULL )
				{
					groupRecordName = strdup(groupname);
					bContinueAdd = true;
					
					// if creating ComputerGroups allow creation of ComputerLists if -L specified
					if ( bCompList == true && grpType == kODRecordTypeComputerGroups ) {
						aGroupRecRef2 = ODNodeCreateRecord( aDSNodeRef, kODRecordTypeComputerLists, groupNameCF, NULL, NULL );
					}
				}
				else
				{
					exitcode = printErrorOrMessage( &aErrorRef, "Unable to create the record", bVerbose );
					break;
				}
			}
		}
		else if (bEditOption)
		{
			if ( aGroupRecRef != NULL ) {
				bContinueAdd = true;
			}
			else {
				printErrorOrMessage( NULL, "Record not found", bVerbose );
				break;
			}
		}
		else if (bCheckMemberOption)
		{
			if ( aGroupRecRef != NULL )
			{
				const char *user = (member ? : username);
				CFStringRef memberCF = CFStringCreateWithCString( kCFAllocatorDefault, user, kCFStringEncodingUTF8 );
				if ( memberCF == NULL ) {
					exitcode = printErrorOrMessage( &aErrorRef, "Unable to to allocate string", bVerbose );
					break;
				}
				
				ODRecordRef memberRec = ODNodeCopyRecord( aDSSearchRef, kODRecordTypeUsers, memberCF, NULL, &aErrorRef );
				if ( memberRec == NULL ) {
					exitcode = printErrorOrMessage( &aErrorRef, "Unable to find the user record", bVerbose );
					break;
				}
				
				if ( ODRecordContainsMember(aGroupRecRef, memberRec, &aErrorRef) == true ) {
					// return default exitcode of 0 if they are a member
					printf("yes %s is a member of %s\n", user, groupname);
					exitcode = EX_OK;
				}
				else {
					printf("no %s is NOT a member of %s\n", user, groupname);
					exitcode = EX_NOUSER;
				}
				
				CFRelease( memberRec );
				CFRelease( memberCF );
			}
			else
			{
				exitcode = printErrorOrMessage( NULL, "Invalid group name", bVerbose );
				break;
			}
		}
Exemplo n.º 7
0
int
od_record_create(pam_handle_t *pamh, ODRecordRef *record, CFStringRef cfUser)
{
	int retval = PAM_SERVICE_ERR;
	const int attr_num = 5;

	ODNodeRef cfNode = NULL;
	CFErrorRef cferror = NULL;
	CFArrayRef attrs = NULL;
	CFTypeRef cfVals[attr_num];

	if (NULL == record || NULL == cfUser) {
		openpam_log(PAM_LOG_DEBUG, "NULL argument passed");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}

#ifdef OPENDIRECTORY_CACHE
#define CFRECORDNAME_CACHE "CFRecordName"
#define CFRECORDNAME_NAME CFSTR("name")
#define CFRECORDNAME_RECORD CFSTR("record")

	CFDictionaryRef cfdict;
	CFStringRef cachedUser;

	if (pam_get_data(pamh, CFRECORDNAME_CACHE, (void *)&cfdict) == PAM_SUCCESS &&
	    (CFGetTypeID(cfdict) == CFDictionaryGetTypeID()) &&
	    (cachedUser = CFDictionaryGetValue(cfdict, CFRECORDNAME_NAME)) != NULL &&
	    CFGetTypeID(cachedUser) == CFStringGetTypeID() &&
	    CFStringCompare(cfUser, cachedUser, 0) == kCFCompareEqualTo &&
	    (*record = (ODRecordRef)CFDictionaryGetValue(cfdict, CFRECORDNAME_RECORD)) != NULL)
	{
		CFRetain(*record);
		return PAM_SUCCESS;
	}
#endif /* OPENDIRECTORY_CACHE */

	int current_iterations = 0;

	cfNode = ODNodeCreateWithNodeType(kCFAllocatorDefault,
					  kODSessionDefault,
					  eDSAuthenticationSearchNodeName,
					  &cferror);
	if (NULL == cfNode || NULL != cferror) {
		openpam_log(PAM_LOG_ERROR, "ODNodeCreateWithNodeType failed.");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}

	cfVals[0] = kODAttributeTypeAuthenticationAuthority;
	cfVals[1] = kODAttributeTypeHomeDirectory;
	cfVals[2] = kODAttributeTypeNFSHomeDirectory;
	cfVals[3] = kODAttributeTypeUserShell;
	cfVals[4] = kODAttributeTypeUniqueID;
	attrs = CFArrayCreate(kCFAllocatorDefault, cfVals, (CFIndex)attr_num, &kCFTypeArrayCallBacks);
	if (NULL == attrs) {
		openpam_log(PAM_LOG_DEBUG, "CFArrayCreate() failed");
		retval = PAM_BUF_ERR;
		goto cleanup;
	}

	retval = PAM_SERVICE_ERR;
	while (current_iterations <= kMaxIterationCount) {
		CFIndex unreachable_count = 0;
		CFArrayRef unreachable_nodes = ODNodeCopyUnreachableSubnodeNames(cfNode, NULL);
		if (unreachable_nodes) {
			unreachable_count = CFArrayGetCount(unreachable_nodes);
			CFRelease(unreachable_nodes);
			openpam_log(PAM_LOG_DEBUG, "%lu OD nodes unreachable.", unreachable_count);
		}

		*record = ODNodeCopyRecord(cfNode, kODRecordTypeUsers, cfUser, attrs, &cferror);
		if (*record)
			break;
		if (0 == unreachable_count)
			break;

		openpam_log(PAM_LOG_DEBUG, "Waiting %d seconds for nodes to become reachable", kWaitSeconds);
		sleep(kWaitSeconds);
		++current_iterations;
	}

	if (*record) {
#ifdef OPENDIRECTORY_CACHE
		const void *keys[] = { CFRECORDNAME_NAME, CFRECORDNAME_RECORD };
		const void *values[] = { cfUser, *record };
		CFDictionaryRef dict;
		
		dict = CFDictionaryCreate(NULL, keys, values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
		if (dict)
			pam_set_data(pamh, CFRECORDNAME_CACHE, (void *)dict, cleanup_cache);
#endif /* OPENDIRECTORY_CACHE */
		retval = PAM_SUCCESS;
	} else {
		retval = PAM_USER_UNKNOWN;
	}

	if (current_iterations > 0) {
		char *wt = NULL, *found = NULL;
		int retval2;

		if (*record)
			found = "failure";
		else
			found = "success";

		retval2 = asprintf(&wt, "%d", kWaitSeconds * current_iterations);
		if (-1 == retval2) {
			openpam_log(PAM_LOG_DEBUG, "Failed to convert current wait time to string.");
			retval = PAM_BUF_ERR;
			goto cleanup;
		}


		aslmsg m = asl_new(ASL_TYPE_MSG);
		asl_set(m, "com.apple.message.domain", "com.apple.pam_modules.odAvailableWaitTime" );
		asl_set(m, "com.apple.message.signature", "wait_time");
		asl_set(m, "com.apple.message.value", wt);
		asl_set(m, "com.apple.message.result", found);
		asl_log(NULL, m, ASL_LEVEL_NOTICE, "OD nodes online delay: %ss. User record lookup: %s.", wt, found);
		asl_free(m);
		free(wt);
	}

cleanup:
	if (NULL != attrs) {
		CFRelease(attrs);
	}

	if (NULL != cferror) {
		CFRelease(cferror);
	}

	if (NULL != cfNode) {
		CFRelease(cfNode);
	}

	if (PAM_SUCCESS != retval) {
		openpam_log(PAM_LOG_ERROR, "failed: %d", retval);
		if (NULL != *record) {
			CFRelease(*record);
			*record = NULL;
		}
	}

	return retval;
}