(root)/
Linux-PAM-1.5.3/
libpamc/
pamc_client.c
       1  /*
       2   * $Id$
       3   *
       4   * Copyright (c) Andrew G. Morgan <morgan@ftp.kernel.org>
       5   *
       6   * pamc_start and pamc_end
       7   */
       8  
       9  #include "libpamc.h"
      10  #include "pam_inline.h"
      11  
      12  /*
      13   * liberate path list
      14   */
      15  
      16  static void __pamc_delete_path_list(pamc_handle_t pch)
      17  {
      18      int i;
      19  
      20      for (i=0; pch->agent_paths[i]; ++i) {
      21  	free(pch->agent_paths[i]);
      22  	pch->agent_paths[i] = NULL;
      23      }
      24  
      25      free(pch->agent_paths);
      26      pch->agent_paths = NULL;
      27  }
      28  
      29  /*
      30   * open the pamc library
      31   */
      32  
      33  pamc_handle_t pamc_start(void)
      34  {
      35      int i, count, last, this;
      36      const char *default_path;
      37      pamc_handle_t pch;
      38  
      39      pch = calloc(1, sizeof(struct pamc_handle_s));
      40      if (pch == NULL) {
      41  	D(("no memory for *pch"));
      42  	return NULL;
      43      }
      44  
      45      pch->highest_fd_to_close = _PAMC_DEFAULT_TOP_FD;
      46  
      47      default_path = getenv("PAMC_AGENT_PATH");
      48      if (default_path == NULL) {
      49  	default_path = PAMC_SYSTEM_AGENT_PATH;
      50      }
      51  
      52      /* number of individual paths */
      53      for (count=1, i=0; default_path[i]; ++i) {
      54  	if (default_path[i] == PAMC_SYSTEM_AGENT_SEPARATOR) {
      55  	    ++count;
      56  	}
      57      }
      58  
      59      pch->agent_paths = calloc(count+1, sizeof(char *));
      60      if (pch->agent_paths == NULL) {
      61  	D(("no memory for path list"));
      62  	goto drop_pch;
      63      }
      64  
      65      this = last = i = 0;
      66      while ( default_path[i] || (i != last) ) {
      67  	if ( default_path[i] == PAMC_SYSTEM_AGENT_SEPARATOR
      68  	     || !default_path[i] ) {
      69  	    int length;
      70  
      71  	    pch->agent_paths[this] = malloc(length = 1+i-last);
      72  
      73  	    if (pch->agent_paths[this] == NULL) {
      74  		D(("no memory for next path"));
      75  		goto drop_list;
      76  	    }
      77  
      78  	    memcpy(pch->agent_paths[this], default_path + last, i-last);
      79  	    pch->agent_paths[this][i-last] = '\0';
      80  	    if (length > pch->max_path) {
      81  		pch->max_path = length;
      82  	    }
      83  
      84  	    if (++this == count) {
      85  		break;
      86  	    }
      87  
      88  	    last = ++i;
      89  	} else {
      90  	    ++i;
      91  	}
      92      }
      93  
      94      return pch;
      95  
      96  drop_list:
      97      __pamc_delete_path_list(pch);
      98  
      99  drop_pch:
     100      free(pch);
     101  
     102      return NULL;
     103  }
     104  
     105  /*
     106   * shutdown each of the loaded agents and
     107   */
     108  
     109  static int __pamc_shutdown_agents(pamc_handle_t pch)
     110  {
     111      int retval = PAM_BPC_TRUE;
     112  
     113      D(("called"));
     114  
     115      while (pch->chain) {
     116  	pid_t pid;
     117  	int status;
     118  	pamc_agent_t *this;
     119  
     120  	this = pch->chain;
     121  	D(("cleaning up agent %p", this));
     122  	pch->chain = pch->chain->next;
     123  	this->next = NULL;
     124  	D(("cleaning up agent: %s", this->id));
     125  
     126  	/* close off contact with agent and wait for it to shutdown */
     127  
     128  	close(this->writer);
     129  	this->writer = -1;
     130  	close(this->reader);
     131  	this->reader = -1;
     132  
     133  	pid = waitpid(this->pid, &status, 0);
     134  	if (pid == this->pid) {
     135  
     136  	    D(("is exit:%d, exit val:%d",
     137  	       WIFEXITED(status), WEXITSTATUS(status)));
     138  
     139  	    if (!(WIFEXITED(status) && (WEXITSTATUS(status) == 0))) {
     140  		retval = PAM_BPC_FALSE;
     141  	    }
     142  	} else {
     143  	    D(("problem shutting down agent (%s): pid(%d) != waitpid(%d)!?",
     144  	       this->id, this->pid, pid));
     145  	    retval = PAM_BPC_FALSE;
     146  	}
     147  	pid = this->pid = 0;
     148  
     149  	pam_overwrite_n(this->id, this->id_length);
     150  	free(this->id);
     151  	this->id = NULL;
     152  	this->id_length = 0;
     153  
     154  	free(this);
     155  	this = NULL;
     156      }
     157  
     158      return retval;
     159  }
     160  
     161  /*
     162   * close the pamc library
     163   */
     164  
     165  int pamc_end(pamc_handle_t *pch_p)
     166  {
     167      int retval;
     168  
     169      if (pch_p == NULL) {
     170  	D(("called with no pch_p"));
     171  	return PAM_BPC_FALSE;
     172      }
     173  
     174      if (*pch_p == NULL) {
     175  	D(("called with no *pch_p"));
     176  	return PAM_BPC_FALSE;
     177      }
     178  
     179      D(("removing path_list"));
     180      __pamc_delete_path_list(*pch_p);
     181  
     182      D(("shutting down agents"));
     183      retval = __pamc_shutdown_agents(*pch_p);
     184  
     185      D(("freeing *pch_p"));
     186      free(*pch_p);
     187      *pch_p = NULL;
     188  
     189      return retval;
     190  }