(root)/
Linux-PAM-1.5.3/
libpam/
pam_modutil_getgrgid.c
       1  /*
       2   * $Id$
       3   *
       4   * This function provides a thread safer version of getgrgid() for use
       5   * with PAM modules that care about this sort of thing.
       6   *
       7   * XXX - or at least it should provide a thread-safe alternative.
       8   */
       9  
      10  #include "pam_modutil_private.h"
      11  
      12  #include <errno.h>
      13  #include <limits.h>
      14  #include <grp.h>
      15  #include <stdio.h>
      16  #include <stdlib.h>
      17  
      18  static int intlen(int number)
      19  {
      20      int len = 2;
      21      while (number != 0) {
      22          number /= 10;
      23  	len++;
      24      }
      25      return len;
      26  }
      27  
      28  static int longlen(long number)
      29  {
      30      int len = 2;
      31      while (number != 0) {
      32          number /= 10;
      33  	len++;
      34      }
      35      return len;
      36  }
      37  
      38  struct group *
      39  pam_modutil_getgrgid(pam_handle_t *pamh, gid_t gid)
      40  {
      41  #ifdef HAVE_GETGRGID_R
      42  
      43      void *buffer=NULL;
      44      size_t length = PWD_INITIAL_LENGTH;
      45  
      46      do {
      47  	int status;
      48  	void *new_buffer;
      49  	struct group *result = NULL;
      50  
      51  	new_buffer = realloc(buffer, sizeof(struct group) + length);
      52  	if (new_buffer == NULL) {
      53  
      54  	    D(("out of memory"));
      55  
      56  	    /* no memory for the user - so delete the memory */
      57  	    if (buffer) {
      58  		free(buffer);
      59  	    }
      60  	    return NULL;
      61  	}
      62  	buffer = new_buffer;
      63  
      64  	/* make the re-entrant call to get the grp structure */
      65  	errno = 0;
      66  	status = getgrgid_r(gid, buffer,
      67  			    sizeof(struct group) + (char *) buffer,
      68  			    length, &result);
      69  	if (!status && (result == buffer)) {
      70  	    char *data_name;
      71  	    const void *ignore;
      72  	    int i;
      73  
      74  	    data_name = malloc(strlen("_pammodutil_getgrgid") + 1 +
      75  			       longlen((long)gid) + 1 + intlen(INT_MAX) + 1);
      76  	    if ((pamh != NULL) && (data_name == NULL)) {
      77  	        D(("was unable to register the data item [%s]",
      78  	           pam_strerror(pamh, status)));
      79  		free(buffer);
      80  		return NULL;
      81  	    }
      82  
      83  	    if (pamh != NULL) {
      84  	        for (i = 0; i < INT_MAX; i++) {
      85  	            sprintf(data_name, "_pammodutil_getgrgid_%ld_%d",
      86  			    (long) gid, i);
      87  		    status = PAM_NO_MODULE_DATA;
      88  	            if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
      89  		        status = pam_set_data(pamh, data_name,
      90  					      result, pam_modutil_cleanup);
      91  		    }
      92  		    if (status == PAM_SUCCESS) {
      93  		        break;
      94  		    }
      95  		}
      96  	    } else {
      97  	        status = PAM_SUCCESS;
      98  	    }
      99  
     100  	    free(data_name);
     101  
     102  	    if (status == PAM_SUCCESS) {
     103  		D(("success"));
     104  		return result;
     105  	    }
     106  
     107  	    D(("was unable to register the data item [%s]",
     108  	       pam_strerror(pamh, status)));
     109  
     110  	    free(buffer);
     111  	    return NULL;
     112  
     113  	} else if (errno != ERANGE && errno != EINTR) {
     114  		/* no sense in repeating the call */
     115  		break;
     116  	}
     117  
     118  	length <<= PWD_LENGTH_SHIFT;
     119  
     120      } while (length < PWD_ABSURD_PWD_LENGTH);
     121  
     122      D(("grp structure took %u bytes or so of memory",
     123         length+sizeof(struct group)));
     124  
     125      free(buffer);
     126      return NULL;
     127  
     128  #else /* ie. ifndef HAVE_GETGRGID_R */
     129  
     130      /*
     131       * Sorry, there does not appear to be a reentrant version of
     132       * getgrgid(). So, we use the standard libc function.
     133       */
     134  
     135      return getgrgid(gid);
     136  
     137  #endif /* def HAVE_GETGRGID_R */
     138  }