1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4 #include "EXTERN.h"
5 #include "perl.h"
6 #include "XSUB.h"
7 #ifdef __cplusplus
8 }
9 #endif
10 
11 #include <PAM_config.h>
12 
13 #if defined( HAVE_SECURITY_PAM_APPL_H )
14 # include <security/pam_appl.h>
15 #else
16 # if defined( HAVE_PAM_PAM_APPL_H )
17 #   include <pam/pam_appl.h>
18 # endif
19 #endif
20 
21 /*
22    Description of the macros used by this file.
23 
24    | If your PAM library has the pam_get/putenv functions (PAM versions
25    | after 0.54) the following macro should be defined.
26    |
27    #define HAVE_PAM_GETENV
28 
29    | The following macro activates a workaround for a bug in the solaris 2.6
30    | PAM library by setting a pointer to the perl conversation function
31    | before every call to a pam function
32    |
33    #define STATIC_CONV_FUNC
34 */
35 
36 
37 /* this is now determined from configure script */
38 
39 
40 #if defined( sun ) || defined( __hpux )
41 
42   #define CONST_VOID	void
43   #define CONST_STRUCT	struct
44 
45 #else
46 
47   #define CONST_STRUCT	const struct
48   #define CONST_VOID	const void
49 
50 #endif
51 
52 struct perl_pam_data {
53   SV* conv_func;
54   SV* delay_func;
55 };
56 
57 typedef struct pam_conv sPamConv;
58 typedef struct pam_response sPamResponse;
59 typedef struct perl_pam_data sPerlPamData;
60 
61 /*
62  * Gets conv_struct->appdata_ptr and casts it as a sPerlPamData
63  */
64 static sPerlPamData*
get_perl_pam_data(pamh)65 get_perl_pam_data(pamh)
66 pam_handle_t *pamh;
67 {
68     int res;
69     sPamConv *cs;
70     res = pam_get_item(pamh, PAM_CONV, (CONST_VOID **)&cs);
71     if (res != PAM_SUCCESS || cs == NULL || cs->appdata_ptr == NULL)
72         croak("Error in getting pam data!");
73     else
74         return (sPerlPamData*)cs->appdata_ptr;
75 }
76 
77 
78 #ifdef STATIC_CONV_FUNC
79 
80     static sPerlPamData *static_perl_pam_data = NULL;
81 
82     #define SET_CONV_FUNC(pamh) static_perl_pam_data = get_perl_pam_data(pamh)
83 
84 #else
85 
86     #define SET_CONV_FUNC(pamh)
87 
88 #endif
89 
90 static int
not_here(s)91 not_here(s)
92 char *s;
93 {
94     croak("%s not implemented on this architecture", s);
95     return -1;
96 }
97 
98 
99 static int
my_conv_func(num_msg,msg,resp,appdata_ptr)100 my_conv_func(num_msg, msg, resp, appdata_ptr)
101         int num_msg;
102         CONST_STRUCT pam_message **msg;
103         sPamResponse **resp;
104         void *appdata_ptr;
105 {
106         int i,res_cnt,res;
107 	STRLEN len;
108         sPamResponse *reply = NULL;
109         SV *strSV;
110         char *str;
111         dSP;
112 
113         ENTER;
114         SAVETMPS;
115 
116         PUSHMARK(sp);
117         for (i = 0; i < num_msg; i++) {
118 	#ifdef sun
119             XPUSHs(sv_2mortal(newSViv((*msg)[i].msg_style)));
120             XPUSHs(sv_2mortal(newSVpv((*msg)[i].msg, 0)));
121 	#else
122             XPUSHs(sv_2mortal(newSViv((msg[i])->msg_style)));
123             XPUSHs(sv_2mortal(newSVpv((msg[i])->msg, 0)));
124 	#endif
125         }
126         PUTBACK;
127 
128 #ifdef STATIC_CONV_FUNC
129 	appdata_ptr = static_perl_pam_data;
130 #endif
131 	if ( !SvTRUE(((sPerlPamData*)appdata_ptr)->conv_func) )
132 	    croak("Calling empty conversation function!");
133         res_cnt =
134 	  perl_call_sv(((sPerlPamData*)appdata_ptr)->conv_func, G_ARRAY);
135 
136         SPAGAIN;
137 
138         if (res_cnt == 1) { // only return code
139 	  res = POPi;
140 	  reply = NULL;
141         }
142 	else if (res_cnt == 2*num_msg + 1) {
143 	    res = POPi;
144 	    res_cnt--;
145 	    if (res_cnt > 0) {
146 		res_cnt /= 2;
147         	reply = malloc( res_cnt * sizeof(sPamResponse));
148         	for (i = res_cnt - 1; i >= 0; i--) {
149         	    strSV = POPs;
150         	    str = SvPV(strSV, len);
151         	    reply[i].resp_retcode = POPi;
152 		    reply[i].resp = malloc(len+1);
153 		    memcpy(reply[i].resp, str, len);
154 		    reply[i].resp[len] = 0;
155 /*
156 		printf("Code %d and str %s\n",  reply[i].resp_retcode,
157 						reply[i].resp);
158 */
159            	}
160 	    }
161         }
162         else {
163 	  croak("The output list of the PAM conversation function"
164 		" must have twice the size of the input list plus one!");
165 	  res = PAM_CONV_ERR;
166 	}
167 
168         PUTBACK;
169 
170         FREETMPS;
171         LEAVE;
172 
173 	*resp = reply;
174 	return res;
175 }
176 
177 
178 /*
179  * We must also handle setting a delay function with a prototype:
180  *
181  *     void (*delay_fn)(int retval, unsigned usec_delay, void *appdata_ptr);
182  *
183  * by a call to pam_set_item(pamh, PAM_FAIL_DELAY, fail_delay);
184  *
185  * Works only on Linux-PAM >= 0.68
186  */
187 static void
my_delay_func(status,delay,appdata_ptr)188 my_delay_func(status, delay, appdata_ptr)
189 int status;
190 unsigned int delay;
191 void *appdata_ptr;
192 {
193     dSP ;
194 
195     if (appdata_ptr == NULL)
196         croak("Empty perl pam data");
197     if (!SvTRUE(((sPerlPamData*)appdata_ptr)->delay_func))
198         croak("Calling empty delay function!");
199 
200     /* printf("st: %d, dl: %d\n",status,delay); */
201 
202     PUSHMARK(sp) ;
203     XPUSHs(sv_2mortal(newSViv(status)));
204     XPUSHs(sv_2mortal(newSViv(delay)));
205     PUTBACK ;
206 
207     perl_call_sv(((sPerlPamData*)appdata_ptr)->delay_func,
208 		 G_VOID | G_DISCARD);
209 }
210 
211 static double
constant(name,arg)212 constant(name, arg)
213 char *name;
214 int arg;
215 {
216     errno = 0;
217 
218     if (strncmp(name, "PAM_", 4) == 0) {
219       name = &name[4];
220       /* error codes */
221       if (strcmp(name, "SUCCESS") == 0)
222 	  return PAM_SUCCESS;
223       else if (strcmp(name, "OPEN_ERR") == 0)
224 	  return PAM_OPEN_ERR;
225       else if (strcmp(name, "SYMBOL_ERR") == 0)
226 	  return PAM_SYMBOL_ERR;
227       else if (strcmp(name, "SERVICE_ERR") == 0)
228 	  return PAM_SERVICE_ERR;
229       else if (strcmp(name, "SYSTEM_ERR") == 0)
230 	  return PAM_SYSTEM_ERR;
231       else if (strcmp(name, "BUF_ERR") == 0)
232 	  return PAM_BUF_ERR;
233       else if (strcmp(name, "PERM_DENIED") == 0)
234 	  return PAM_PERM_DENIED;
235       else if (strcmp(name, "AUTH_ERR") == 0)
236 	  return PAM_AUTH_ERR;
237       else if (strcmp(name, "CRED_INSUFFICIENT") == 0)
238 	  return PAM_CRED_INSUFFICIENT;
239       else if (strcmp(name, "AUTHINFO_UNAVAIL") == 0)
240 	  return PAM_AUTHINFO_UNAVAIL;
241       else if (strcmp(name, "USER_UNKNOWN") == 0)
242 	  return PAM_USER_UNKNOWN;
243       else if (strcmp(name, "MAXTRIES") == 0)
244 	  return PAM_MAXTRIES;
245       else if (strcmp(name, "NEW_AUTHTOK_REQD") == 0 ||
246 	       strcmp(name, "AUTHTOKEN_REQD") == 0)
247       #if defined(HAVE_PAM_NEW_AUTHTOK_REQD)
248 	  return PAM_NEW_AUTHTOK_REQD;
249       #elif defined(HAVE_PAM_AUTHTOKEN_REQD)
250           return PAM_AUTHTOKEN_REQD;       /* Old Linux-PAM */
251       #else
252 	  goto not_there;
253       #endif
254       else if (strcmp(name, "ACCT_EXPIRED") == 0)
255 	  return PAM_ACCT_EXPIRED;
256       else if (strcmp(name, "SESSION_ERR") == 0)
257 	  return PAM_SESSION_ERR;
258       else if (strcmp(name, "CRED_UNAVAIL") == 0)
259 	  return PAM_CRED_UNAVAIL;
260       else if (strcmp(name, "CRED_EXPIRED") == 0)
261 	  return PAM_CRED_EXPIRED;
262       else if (strcmp(name, "CRED_ERR") == 0)
263 	  return PAM_CRED_ERR;
264       else if (strcmp(name, "NO_MODULE_DATA") == 0)
265 	  return PAM_NO_MODULE_DATA;
266       else if (strcmp(name, "CONV_ERR") == 0)
267 	  return PAM_CONV_ERR;
268       else if (strcmp(name, "AUTHTOK_ERR") == 0)
269 	  return PAM_AUTHTOK_ERR;
270       else if (strcmp(name, "AUTHTOK_RECOVER_ERR") == 0 ||
271 	       strcmp(name, "AUTHTOK_RECOVERY_ERR") == 0)
272       #if defined(HAVE_PAM_AUTHTOK_RECOVER_ERR)    /* Linux-PAM   */
273 	  return PAM_AUTHTOK_RECOVER_ERR;
274       #elif defined(HAVE_PAM_AUTHTOK_RECOVERY_ERR) /* Solaris PAM */
275 	  return PAM_AUTHTOK_RECOVERY_ERR;
276       #else
277 	  goto not_there;
278       #endif
279       else if (strcmp(name, "AUTHTOK_LOCK_BUSY") == 0)
280 	  return PAM_AUTHTOK_LOCK_BUSY;
281       else if (strcmp(name, "AUTHTOK_DISABLE_AGING") == 0)
282 	  return PAM_AUTHTOK_DISABLE_AGING;
283       else if (strcmp(name, "TRY_AGAIN") == 0)
284 	  return PAM_TRY_AGAIN;
285       else if (strcmp(name, "IGNORE") == 0)
286 	  return PAM_IGNORE;
287       else if (strcmp(name, "ABORT") == 0)
288 	  return PAM_ABORT;
289       else if (strcmp(name, "AUTHTOK_EXPIRED") == 0)
290       #if defined(HAVE_PAM_AUTHTOK_EXPIRED)
291 	  return PAM_AUTHTOK_EXPIRED;
292       #else
293 	  goto not_there;
294       #endif
295       else if (strcmp(name, "MODULE_UNKNOWN") == 0)
296       #if defined(HAVE_PAM_MODULE_UNKNOWN)  /* Linux-PAM only */
297 	  return PAM_MODULE_UNKNOWN;
298       #else
299 	  goto not_there;
300       #endif
301       else if (strcmp(name, "BAD_ITEM") == 0)
302       #if defined(HAVE_PAM_BAD_ITEM)
303 	  return PAM_BAD_ITEM;
304       #else
305 	  goto not_there;
306       #endif
307 
308       /* New Linux-PAM return codes */
309       else if (strcmp(name, "CONV_AGAIN") == 0)
310       #if defined(HAVE_PAM_CONV_AGAIN)
311 	  return PAM_CONV_AGAIN;
312       #else
313 	  goto not_there;
314       #endif
315       else if (strcmp(name, "INCOMPLETE") == 0)
316       #if defined(HAVE_PAM_INCOMPLETE)
317 	  return PAM_INCOMPLETE;
318       #else
319 	  goto not_there;
320       #endif
321 
322       /* set/get_item constants */
323       else if (strcmp(name, "SERVICE") == 0)
324 	  return PAM_SERVICE;
325       else if (strcmp(name, "USER") == 0)
326 	  return PAM_USER;
327       else if (strcmp(name, "TTY") == 0)
328 	  return PAM_TTY;
329       else if (strcmp(name, "RHOST") == 0)
330 	  return PAM_RHOST;
331       else if (strcmp(name, "CONV") == 0)
332 	  return PAM_CONV;
333       /* module flags */
334       /*
335       else if (strcmp(name, "AUTHTOK") == 0)
336 	  return PAM_CONV;
337       else if (strcmp(name, "OLDAUTHTOK") == 0)
338 	  return PAM_CONV;
339       */
340       else if (strcmp(name, "RUSER") == 0)
341 	  return PAM_RUSER;
342       else if (strcmp(name, "USER_PROMPT") == 0)
343 	  return PAM_USER_PROMPT;
344       else if (strcmp(name, "FAIL_DELAY") == 0)
345       #if defined(HAVE_PAM_FAIL_DELAY)
346 	  return PAM_FAIL_DELAY;
347       #else
348 	  goto not_there;
349       #endif
350 
351       /* global flag */
352       else if (strcmp(name, "SILENT") == 0)
353 	  return PAM_SILENT;
354       /* pam_authenticate falgs */
355       else if (strcmp(name, "DISALLOW_NULL_AUTHTOK") == 0)
356 	  return PAM_DISALLOW_NULL_AUTHTOK;
357       /* pam_set_cred flags */
358       else if (strcmp(name, "ESTABLISH_CRED") == 0 ||
359 	       strcmp(name, "CRED_ESTABLISH") == 0)
360       #if defined(HAVE_PAM_ESTABLISH_CRED)
361 	  return PAM_ESTABLISH_CRED;
362       #elif defined(HAVE_PAM_CRED_ESTABLISH)   /* Old Linux-PAM */
363 	  return PAM_CRED_ESTABLISH;
364       #else
365 	  goto not_there;
366       #endif
367       else if (strcmp(name, "DELETE_CRED") == 0 ||
368 	       strcmp(name, "CRED_DELETE") == 0)
369       #if defined(HAVE_PAM_DELETE_CRED)
370 	  return PAM_DELETE_CRED;
371       #elif defined(HAVE_PAM_CRED_DELETE)       /* Old Linux-PAM */
372 	  return PAM_CRED_DELETE;
373       #else
374 	  goto not_there;
375       #endif
376       else if (strcmp(name, "REINITIALIZE_CRED") == 0 ||
377 	       strcmp(name, "CRED_REINITIALIZE") == 0)
378       #if defined(HAVE_PAM_REINITIALIZE_CRED)
379 	  return PAM_REINITIALIZE_CRED;
380       #elif defined(HAVE_PAM_CRED_REINITIALIZE)
381 	  return PAM_CRED_REINITIALIZE;    /* Old Linux-PAM */
382       #else
383 	  goto not_there;
384       #endif
385       else if (strcmp(name, "REFRESH_CRED") == 0 ||
386 	       strcmp(name, "CRED_REFRESH") == 0)
387       #if defined(HAVE_PAM_REFRESH_CRED)
388 	  return PAM_REFRESH_CRED;
389       #elif defined(HAVE_PAM_CRED_REFRESH)
390 	  return PAM_CRED_REFRESH;         /* Old Linux-PAM */
391       #else
392 	  goto not_there;
393       #endif
394       /* pam_chauthtok flags */
395       else if (strcmp(name, "CHANGE_EXPIRED_AUTHTOK") == 0)
396 	  return PAM_CHANGE_EXPIRED_AUTHTOK;
397 
398       /* message style constants */
399       else if (strcmp(name, "PROMPT_ECHO_OFF") == 0)
400 	  return PAM_PROMPT_ECHO_OFF;
401       else if (strcmp(name, "PROMPT_ECHO_ON") == 0)
402 	  return PAM_PROMPT_ECHO_ON;
403       else if (strcmp(name, "ERROR_MSG") == 0)
404 	  return PAM_ERROR_MSG;
405       else if (strcmp(name, "TEXT_INFO") == 0)
406 	  return PAM_TEXT_INFO;
407       else if (strcmp(name, "RADIO_TYPE") == 0)
408       #if defined(HAVE_PAM_RADIO_TYPE)
409 	  return PAM_RADIO_TYPE;
410       #else
411 	  goto not_there;
412       #endif
413       else if (strcmp(name, "BINARY_PROMPT") == 0)
414       #if defined(HAVE_PAM_BINARY_PROMPT)
415 	  return PAM_BINARY_PROMPT;
416       #else
417 	  goto not_there;
418       #endif
419 
420       /* I'm not sure if these are really needed... */
421       /*
422       else if (strcmp(name, "MAX_MSG_SIZE") == 0)
423 	  return PAM_MAX_MSG_SIZE;
424       else if (strcmp(name, "MAX_RESP_SIZE") == 0)
425 	  return PAM_MAX_RESP_SIZE;
426       */
427     }
428     else if (strncmp(name, "HAVE_PAM_", 9) == 0) {
429       name = &name[9];
430 
431       if (strcmp(name, "FAIL_DELAY") == 0)
432       #if defined(HAVE_PAM_FAIL_DELAY)
433 	  return 1;
434       #else
435 	  return 0;
436       #endif
437       else if (strcmp(name, "ENV_FUNCTIONS") == 0)
438       #if defined(HAVE_PAM_GETENV)
439 	  return 1;
440       #else
441 	  return 0;
442       #endif
443       /*
444       else if (strcmp(name, "HAVE_PAM_SYSTEM_LOG") == 0)
445       #if defined(HAVE_PAM_SYSTEM_LOG)
446 	  return 1;
447       #else
448 	  return 0;
449       #endif
450       */
451     }
452 
453     errno = EINVAL;
454     return 0;
455 
456 not_there:
457     errno = ENOSYS;
458     return 0;
459 }
460 
461 
462 MODULE = Authen::PAM	PACKAGE = Authen::PAM
463 
464 PROTOTYPES: ENABLE
465 
466 
467 double
468 constant(name,arg)
469 	char	*name
470 	int	arg
471 
472 
473 int
474 _pam_start(service_name, user_sv, func, pamh)
475 	const char *service_name
476 	SV *user_sv
477 	SV *func
478 	pam_handle_t *pamh = NO_INIT
479 	PREINIT:
480 	  sPamConv conv_st;
481 	  const char *user;
482 	CODE:
483 	  user = SvOK(user_sv) ? SvPV_nolen(user_sv) : NULL;
484 
485 	  conv_st.conv = my_conv_func;
486 	  conv_st.appdata_ptr = malloc(sizeof(sPerlPamData));
487 	  ((sPerlPamData*)conv_st.appdata_ptr)->conv_func = newSVsv(func);
488 	  ((sPerlPamData*)conv_st.appdata_ptr)->delay_func = newSViv(0);
489 
490 	  RETVAL = pam_start(service_name, user, &conv_st, &pamh);
491         OUTPUT:
492 	  pamh
493 	  RETVAL
494 
495 int
496 pam_end(pamh, pam_status=PAM_SUCCESS)
497 	pam_handle_t *pamh
498 	int	pam_status
499 	PREINIT:
500 	  sPerlPamData *data;
501 	  int res;
502 	CODE:
503 	  data = get_perl_pam_data(pamh);
504           SvREFCNT_dec(data->conv_func);
505           SvREFCNT_dec(data->delay_func);
506 	  free(data);
507 
508           RETVAL = pam_end(pamh, pam_status);
509 	OUTPUT:
510 	RETVAL
511 
512 int
pam_set_item(pamh,item_type,item)513 pam_set_item(pamh, item_type, item)
514 	pam_handle_t *pamh
515 	int	item_type
516 	SV	*item
517 	PREINIT:
518 	  sPerlPamData *data;
519 	  int res;
520 	CODE:
521 	  if (item_type == PAM_CONV) {
522 	      data = get_perl_pam_data(pamh);
523 	      sv_setsv(data->conv_func, item);
524 	      RETVAL = PAM_SUCCESS;
525 	  }
526 #if defined(HAVE_PAM_FAIL_DELAY)
527           else if (item_type == PAM_FAIL_DELAY) {
528 	      data = get_perl_pam_data(pamh);
529 	      sv_setsv(data->delay_func, item);
530 	      if (SvTRUE(item))
531 	          RETVAL = pam_set_item( pamh, item_type, my_delay_func);
532 	      else
533 	          RETVAL = pam_set_item( pamh, item_type, NULL);
534 	  }
535 #endif
536 	  else
537 #if (PERL_API_REVISION == 5 && PERL_API_VERSION >= 5)
538 	      RETVAL = pam_set_item( pamh, item_type, SvPV_nolen(item));
539 #else
540 	      RETVAL = pam_set_item( pamh, item_type, SvPV(item,na));
541 #endif
542 	OUTPUT:
543 	RETVAL
544 
545 int
pam_get_item(pamh,item_type,item)546 pam_get_item(pamh, item_type, item)
547 	pam_handle_t *pamh
548 	int	item_type
549 	SV	*item
550 	PREINIT:
551 	  char *c;
552 	  sPerlPamData *data;
553 	  int res;
554 	CODE:
555 	  if (item_type == PAM_CONV) {
556 	      data = get_perl_pam_data(pamh);
557 	      sv_setsv(item, data->conv_func);
558 	      RETVAL = PAM_SUCCESS;
559 	  }
560 #if defined(HAVE_PAM_FAIL_DELAY)
561           else if (item_type == PAM_FAIL_DELAY) {
562 	      data = get_perl_pam_data(pamh);
563 	      sv_setsv(item, data->delay_func);
564 	      RETVAL = PAM_SUCCESS;
565  	  }
566 #endif
567 	  else {
568 	      RETVAL = pam_get_item( pamh, item_type, (CONST_VOID **)&c);
569 	      sv_setpv(item, c);
570 	  }
571 	OUTPUT:
572 	item
573 	RETVAL
574 
575 const char *
576 pam_strerror(pamh, errnum)
577 	pam_handle_t *	pamh
578 	int	errnum
579 	CODE:
580 #if defined(PAM_STRERROR_NEEDS_PAMH)
581 	  RETVAL = pam_strerror(pamh, errnum);
582 #else
583 	  RETVAL = pam_strerror(errnum);
584 #endif
585 	OUTPUT:
586 	RETVAL
587 
588 #if defined(HAVE_PAM_GETENV)
589 int
590 pam_putenv(pamh, name_value)
591 	pam_handle_t	*pamh
592 	const char	*name_value
593 	CODE:
594 	  RETVAL = pam_putenv(pamh, name_value);
595 	OUTPUT:
596 	RETVAL
597 
598 const char *
599 pam_getenv(pamh, name)
600 	pam_handle_t	*pamh
601 	const char	*name
602 	CODE:
603 	  RETVAL = pam_getenv(pamh, name);
604 	OUTPUT:
605 	RETVAL
606 
607 void
608 _pam_getenvlist(pamh)
609 	pam_handle_t *pamh
610 	PREINIT:
611 	  char **res;
612 	  int i;
613 	  int c;
614 	PPCODE:
615 	  res = pam_getenvlist(pamh);
616 	  c = 0;
617 	  while (res[c] != 0)
618 	      c++;
619 	  EXTEND(sp, c);
620 	  for (i = 0; i < c; i++)
621 	      PUSHs(sv_2mortal(newSVpv(res[i],0)));
622 
623 #else
624 
625 int
626 pam_putenv(pamh, name_value)
627 	pam_handle_t	*pamh
628 	const char	*name_value
629 	CODE:
630 	  not_here("pam_putenv");
631 
632 const char *
633 pam_getenv(pamh, name)
634 	pam_handle_t	*pamh
635 	const char	*name
636 	CODE:
637 	  not_here("pam_getenv");
638 
639 
640 void
641 _pam_getenvlist(pamh)
642 	pam_handle_t *pamh
643 	CODE:
644 	  not_here("pam_getenvlist");
645 
646 #endif
647 
648 
649 #if defined(HAVE_PAM_FAIL_DELAY)
650 
651 int
652 pam_fail_delay(pamh, musec_delay)
653 	pam_handle_t *pamh
654 	unsigned int musec_delay
655 	CODE:
656 	  RETVAL = pam_fail_delay(pamh, musec_delay);
657 	OUTPUT:
658 	RETVAL
659 
660 #else
661 
662 void
663 pam_fail_delay(pamh, musec_delay)
664 	pam_handle_t *	pamh
665 	unsigned int	musec_delay
666 	CODE:
667 	  not_here("pam_fail_delay");
668 
669 #endif
670 
671 
672 int
673 pam_authenticate(pamh, flags=0)
674 	pam_handle_t *pamh
675 	int	flags
676 	CODE:
677 	  SET_CONV_FUNC(pamh);
678 	  RETVAL = pam_authenticate(pamh,flags);
679 	OUTPUT:
680 	RETVAL
681 
682 int
683 pam_setcred(pamh, flags)
684 	pam_handle_t *pamh
685 	int	flags
686 	CODE:
687 	  SET_CONV_FUNC(pamh);
688 	  RETVAL = pam_setcred(pamh,flags);
689 	OUTPUT:
690 	RETVAL
691 
692 int
693 pam_acct_mgmt(pamh, flags=0)
694 	pam_handle_t *pamh
695 	int	flags
696 	CODE:
697 	  SET_CONV_FUNC(pamh);
698 	  RETVAL = pam_acct_mgmt(pamh,flags);
699 	OUTPUT:
700 	RETVAL
701 
702 int
703 pam_open_session(pamh, flags=0)
704 	pam_handle_t *pamh
705 	int	flags
706 	CODE:
707 	  SET_CONV_FUNC(pamh);
708 	  RETVAL = pam_open_session(pamh,flags);
709 	OUTPUT:
710 	RETVAL
711 
712 int
713 pam_close_session(pamh, flags=0)
714 	pam_handle_t *pamh
715 	int	flags
716 	CODE:
717 	  SET_CONV_FUNC(pamh);
718 	  RETVAL = pam_close_session(pamh, flags);
719 	OUTPUT:
720 	RETVAL
721 
722 int
723 pam_chauthtok(pamh, flags=0)
724 	pam_handle_t *pamh
725 	int	flags
726 	CODE:
727 	  SET_CONV_FUNC(pamh);
728 	  RETVAL = pam_chauthtok(pamh, flags);
729 	OUTPUT:
730 	RETVAL
731