putuserattrs Subroutine

Purpose

Stores multiple user attributes in the user database.

Library

Security Library (libc.a)

Syntax

#include <usersec.h>

int putuserattrs (UserAttributesCount)
char * User;
dbattr_t * Attributes;
int Count

Description

The putuserattrs subroutine writes multiple user attributes into the user database. If the database is not already open, this subroutine does an implicit open for reading and writing. Data changed by putuserattrs must be explicitly committed by calling the putuserattr subroutine with a Type parameter specifying the SEC_COMMIT value. Until the data is committed, only get subroutine calls within the process return the written data.

The Attributes array contains information about each attribute that is to be written. Each element in the Attributes array must be examined upon a successful call to putuserattrs to determine if the Attributes array entry was successfully put. Please see putuserattr man page for the supported attributes. The dbattr_t data structure contains the following fields:
attr_name
The name of the desired attribute.
attr_idx
Used internally by the putuserattrs subroutine.
attr_type
The type of the desired attribute. The list of attribute types is defined in the usersec.h header file.
S_DOMAINS
The domains for the user. It can be one or more. The attribute type is SEC_LIST.
attr_flag
The results of the request to write the desired attribute.
attr_un
A union containing the returned values. Its union members that follow correspond to the definitions of the attr_char, attr_int, attr_long, and attr_llong macros, respectively:
au_char
Attributes of type SEC_CHAR and SEC_LIST contain a pointer to the value to be written.
au_int
Attributes of type SEC_INT and SEC_BOOL contain the value of the attribute to be written.
au_long
Attributes of type SEC_LONG contain the value of the attribute to be written.
au_llong
Attributes of type SEC_LLONG contain the value of the attribute to be written.
attr_domain
The authentication domain containing the attribute. The putuserattrs subroutine stores the name of the authentication domain that was used to write this attribute if it is not initialized by the caller. The putuserattrs subroutine is responsible for managing the memory referenced by this pointer. If attr_domain is specified for an attribute, the put request is sent only to that domain. If attr_domain is not specified (that is, set to NULL), putuserattrs attempts to put the attributes to the first domain associated with the user. All put requests for the attributes with a NULL attr_domain are sent to the same domain. In other words, values cannot be put into different domains where attr_domain is unspecified; attr_domain is set to the name of the domain where the value is put and returned to the invoker. When attr_domain is not specified, the list of searchable domains can be restricted to a particular domain by using the setauthdb function call.

Use the setuserdb and enduserdb subroutines to open and close the user database. Failure to explicitly open and close the user database can result in loss of memory and performance.

Parameters

Item Description
User Specifies the name of the user for which the attributes are to be written.
Attributes A pointer to an array of one or more elements of type dbattr_t. The list of user attributes is defined in the usersec.h header file.
Count The number of array elements in Attributes.

Security

Files accessed:

Item Description
Mode File
rw /etc/group
rw /etc/passwd
rw /etc/security/audit/config
rw /etc/security/environ
rw /etc/security/group
rw /etc/security/lastlog
rw /etc/security/limits
rw /etc/security/passwd
rw /etc/security/pwdhist.dir
rw /etc/security/pwdhist.pag
rw /etc/security/smitacl.user
rw /etc/security/user.roles

Return Values

The putuserattrs subroutine returns a value of 0 if the User exists, even in the case when no attributes in the Attributes array were successfully updated. Otherwise, a value of -1 is returned and the errno global variable is set to indicate the error.

Error Codes

The putuserattrs subroutine fails if one or more of the following is true:

Item Description
EACCES The system information database could not be accessed for writing.
EINVAL The User parameter is the NULL pointer.
EINVAL The Attributes parameter does not point to valid data for the requested attribute. Limited testing is possible and all errors might not be detected.
EINVAL The Attributes parameter does not point to valid data for the requested attribute. Limited testing is possible and all errors might not be detected.
ENOENT The specified User parameter does not exist.

If the putuserattrs subroutine fails to write an attribute, one or more of the following errors is returned in the attr_flag field of the corresponding Attributes element:

Item Description
EACCES The user does not have access to the attribute specified in the attr_name field.
EINVAL The attr_type field in the Attributes entry contains an invalid type.
EINVAL The attr_un field in the Attributes entry does not point to a valid buffer or to valid data for this type of attribute. Limited testing is possible and all errors might not be detected.
ENOATTR The attr_name field in the Attributes entry specifies an attribute that is not defined for this user.

Examples

The following sample test program displays the output to a call to putuserattrs. In this example, the system has a user named foo.

#include <stdio.h> 
#include <strings.h>
#include <string.h>
#include <usersec.h>


char * CommaToNSL(char *);

#define NATTR 		4  	 /* Number of attributes to be put */
#define USERNAME	"foo"    /* User name */
#define DOMAIN		"files"  /* domain where attributes are going to put. */

main(int argc, char *argv[]) {
	int 	 rc;
	int 	 i;
	dbattr_t attributes[NATTR];

        /* Open the user database */
        setuserdb(S_WRITE);

	/* Valid put */

	attributes[0].attr_name = S_GECOS;
        attributes[0].attr_type = SEC_CHAR;
	attributes[0].attr_domain = DOMAIN;
	attributes[0].attr_char = strdup("I am foo");

	/* Invalid put */

	attributes[1].attr_name = S_LOGINCHK;
        attributes[1].attr_type = SEC_BOOL;
	attributes[1].attr_domain = DOMAIN;
	attributes[1].attr_char = strdup("allow");

	/* Valid put */

	attributes[2].attr_name = S_MAXAGE;
	attributes[2].attr_type = SEC_INT;
	attributes[2].attr_domain = DOMAIN;
	attributes[2].attr_int = 10;

	/* Valid put */

	attributes[3].attr_name = S_GROUPS;
	attributes[3].attr_type = SEC_LIST;
	attributes[3].attr_domain = DOMAIN;
	attributes[3].attr_char = CommaToNSL("staff,system");

	rc = putuserattrs(USERNAME, attributes, NATTR); 

	if (rc) {
		printf("putuserattrs failed \n");
		goto clean_exit;
	}

	for (i = 0; i < NATTR; i++) {
		if (attributes[i].attr_flag)
			printf("Put failed for attribute %s. errno = %d \n",
			    attributes[i].attr_name, attributes[i].attr_flag);
		else
			printf("Put succeded for attribute %s \n",
			    attributes[i].attr_name);
	}

clean_exit:
        enduserdb();

	if (attributes[0].attr_char)
                free(attributes[0].attr_char);

        if (attributes[1].attr_char)
                free(attributes[1].attr_char);

        if (attributes[3].attr_char)
                free(attributes[3].attr_char);

	exit(rc);
}

/*
 * Returns a new NSL created from a comma separated list.
 * The comma separated list is unmodified.
 *
 */
char *
CommaToNSL(char *CommaList)
{
        char    *NSL = (char *) NULL;
        char    *s;

        if (!CommaList)
        	return(NSL);

        if (!(NSL = (char *) malloc(strlen(CommaList) + 2)))
        	return(NSL);

        strcpy(NSL, CommaList);

        for (s = NSL; *s; s++)
                if (*s == ',')
                        *s = '\0';

        *(++s) = '\0';
}
The following output for the call is expected:
Put succeeded for attribute gecos
Put failed for attribute login (errno = 22)
Put succeeded for attribute maxage
Put succeeded for attribute groups