(file) Return to PAMAuth.h CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Executor

  1 kumpf 1.2 /*
  2           //%2006////////////////////////////////////////////////////////////////////////
  3           //
  4           // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  5           // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  6           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  7           // IBM Corp.; EMC Corporation, The Open Group.
  8           // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  9           // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
 10           // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 11           // EMC Corporation; VERITAS Software Corporation; The Open Group.
 12           // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 13           // EMC Corporation; Symantec Corporation; The Open Group.
 14           //
 15           // Permission is hereby granted, free of charge, to any person obtaining a copy
 16           // of this software and associated documentation files (the "Software"), to
 17           // deal in the Software without restriction, including without limitation the
 18           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 19           // sell copies of the Software, and to permit persons to whom the Software is
 20           // furnished to do so, subject to the following conditions:
 21           // 
 22 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 23           // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 24           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 25           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 26           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 27           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 28           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 29           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 30           //
 31           //==============================================================================
 32           //
 33           //%/////////////////////////////////////////////////////////////////////////////
 34           */
 35           
 36           #ifndef Executor_PAMAuth_h
 37           #define Executor_PAMAuth_h
 38           
 39           #if !defined(PEGASUS_PAM_AUTHENTICATION)
 40           # error "Do not include this file without defining PEGASUS_PAM_AUTHENTICATION"
 41           #endif
 42           
 43 kumpf 1.2 #include <sys/types.h>
 44           #include <sys/socket.h>
 45           #include <sys/wait.h>
 46           #include <unistd.h>
 47           #include <stdio.h>
 48           #include <errno.h>
 49           #include <string.h>
 50           #include <Executor/Strlcpy.h>
 51           #include <Executor/Strlcat.h>
 52           #include <security/pam_appl.h>
 53           #include "Defines.h"
 54           
 55           /*
 56           **==============================================================================
 57           **
 58           **     This program is used to authenticate users with the "Basic PAM
 59           **     Authentication" scheme. It was originally written to isolate memory
 60           **     PAM module errors to an external process.
 61           **
 62           **     This header defines two functions that may be called by clients of this
 63           **     process (the parent process).
 64 kumpf 1.2 **
 65           **         CimserveraAuthenticate()
 66           **         CimserveraValidateUser()
 67           **
 68           **     Each functions forks and executes a child process that carries out
 69           **     the request and then exits immediately. The parent and child proceses
 70           **     communicate over a local domain socket, created by the parent just
 71           **     before executing the client program.
 72           **
 73           **     Both of the functions above are defined in the header to avoid the need
 74           **     to link a separate client library.
 75           **
 76           **     CAUTION: This program must not depend on any Pegasus libraries since
 77           **     it is used by the executor process.
 78           **
 79           **==============================================================================
 80           */
 81           
 82           /*
 83           **==============================================================================
 84           **
 85 kumpf 1.2 ** CimserveraSend()
 86           **
 87           **     Sends *size* bytes on the given socket.
 88           **
 89           **==============================================================================
 90           */
 91           
 92           static ssize_t CimserveraSend(int sock, void* buffer, size_t size)
 93           {
 94               size_t r = size;
 95               char* p = (char*)buffer;
 96           
 97               while (r)
 98               {
 99                   ssize_t n;
100                   EXECUTOR_RESTART(write(sock, p, r), n);
101           
102                   if (n == -1)
103                       return -1;
104                   else if (n == 0)
105                       return size - r;
106 kumpf 1.2 
107                   r -= n;
108                   p += n;
109               }
110           
111               return size - r;
112           }
113           
114           /*
115           **==============================================================================
116           **
117           ** CimserveraStart()
118           **
119           **     Starts the CIMSERVERA program, returning a socket used to communicate
120           **     with it.
121           **
122           **==============================================================================
123           */
124           
125           static int CimserveraStart(int* sock)
126           {
127 kumpf 1.2     int pair[2];
128               int pid;
129           
130               /* Get absolute path of CIMSERVERA program. */
131           
132               char path[EXECUTOR_BUFFER_SIZE];
133           
134               if (PEGASUS_PAM_STANDALONE_PROC_NAME[0] == '/')
135                   Strlcpy(path, PEGASUS_PAM_STANDALONE_PROC_NAME, EXECUTOR_BUFFER_SIZE);
136               else
137               {
138                   /* Flawfinder: ignore */
139                   const char* home = getenv("PEGASUS_HOME");
140           
141                   if (!home)
142                       return -1;
143           
144                   Strlcpy(path, home, EXECUTOR_BUFFER_SIZE);
145                   Strlcat(path, "/", EXECUTOR_BUFFER_SIZE);
146                   Strlcat(path, PEGASUS_PAM_STANDALONE_PROC_NAME, EXECUTOR_BUFFER_SIZE);
147               }
148 kumpf 1.2 
149               /* Create socket pair for communicating with child process. */
150           
151               if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) != 0)
152                   return -1;
153           
154               /* Fork child: */
155           
156               pid = fork();
157           
158               if (pid < 0)
159 kumpf 1.3     {
160                   close(pair[0]);
161                   close(pair[1]);
162 kumpf 1.2         return -1;
163 kumpf 1.3     }
164 kumpf 1.2 
165               /* Child process: */
166           
167               if (pid == 0)
168               {
169                   char sockStr[32];
170                   const char* argv[3];
171           
172                   close(pair[1]);
173           
174                   /* Convert socket number to string. */
175           
176                   sprintf(sockStr, "%d", pair[0]);
177           
178                   /* Build arguments for execv(). */
179           
180                   argv[0] = CIMSERVERA;
181                   argv[1] = sockStr;
182                   argv[2] = 0;
183           
184                   /* Execute child: */
185 kumpf 1.2 
186                   /* Flawfinder: ignore */
187                   execv(path, (char**)argv);
188                   close(pair[0]);
189                   _exit(0);
190               }
191           
192               /* Parent process: */
193           
194               close(pair[0]);
195           
196               *sock = pair[1];
197               return pid;
198           }
199           
200           /*
201           **==============================================================================
202           **
203           ** CimserveraRequest
204           **
205           **==============================================================================
206 kumpf 1.2 */
207           
208           typedef struct CimserveraRequestStruct
209           {
210               char arg0[EXECUTOR_BUFFER_SIZE];
211               char arg1[EXECUTOR_BUFFER_SIZE];
212               char arg2[EXECUTOR_BUFFER_SIZE];
213           }
214           CimserveraRequest;
215           
216           /*
217           **==============================================================================
218           **
219           ** CimserveraAuthenticate()
220           **
221           **==============================================================================
222           */
223           
224           static int CimserveraAuthenticate(const char* username, const char* password)
225           {
226               int sock;
227 kumpf 1.2     int pid;
228               int status;
229           
230               /* Create the CIMSERVERA process. */
231           
232               pid = CimserveraStart(&sock);
233           
234               if (pid == -1)
235                   return -1;
236           
237               /* Send request, get response. */
238           
239               status = 0;
240           
241               do
242               {
243                   CimserveraRequest request;
244                   int childStatus;
245           
246                   /* Send request to CIMSERVERA process. */
247           
248 kumpf 1.2         memset(&request, 0, sizeof(request));
249                   Strlcpy(request.arg0, "authenticate", EXECUTOR_BUFFER_SIZE);
250                   Strlcpy(request.arg1, username, EXECUTOR_BUFFER_SIZE);
251                   Strlcpy(request.arg2, password, EXECUTOR_BUFFER_SIZE);
252           
253                   if (CimserveraSend(sock, &request, sizeof(request)) != sizeof(request))
254                   {
255                       status = -1;
256                       break;
257                   }
258           
259                   /* Get exit status from CIMSERVERA program. */
260           
261                   waitpid(pid, &childStatus, 0);
262           
263                   if (!WIFEXITED(childStatus) || WEXITSTATUS(childStatus) != 0)
264                   {
265                       status = -1;
266                       break;
267                   }
268               }
269 kumpf 1.2     while (0);
270           
271               close(sock);
272           
273               return status;
274           }
275           
276           /*
277           **==============================================================================
278           **
279           ** CimserveraValidateUser()
280           **
281           **==============================================================================
282           */
283           
284           static int CimserveraValidateUser(const char* username)
285           {
286               int sock;
287               int pid;
288               int status;
289           
290 kumpf 1.2     /* Create the CIMSERVERA process. */
291           
292               pid = CimserveraStart(&sock);
293           
294               if (pid == -1)
295                   return -1;
296           
297               /* Send request, get response. */
298           
299               status = 0;
300           
301               do
302               {
303                   CimserveraRequest request;
304                   int childStatus;
305           
306                   /* Send request to CIMSERVERA process. */
307           
308                   memset(&request, 0, sizeof(request));
309                   Strlcpy(request.arg0, "validateUser", EXECUTOR_BUFFER_SIZE);
310                   Strlcpy(request.arg1, username, EXECUTOR_BUFFER_SIZE);
311 kumpf 1.2 
312                   if (CimserveraSend(sock, &request, sizeof(request)) != sizeof(request))
313                   {
314                       status = -1;
315                       break;
316                   }
317           
318                   /* Get exit status from CIMSERVERA program. */
319           
320                   waitpid(pid, &childStatus, 0);
321           
322                   if (!WIFEXITED(childStatus) || WEXITSTATUS(childStatus) != 0)
323                   {
324                       status = -1;
325                       break;
326                   }
327               }
328               while (0);
329           
330               close(sock);
331           
332 kumpf 1.2     return status;
333           }
334           
335           /*
336           **==============================================================================
337           **
338           ** struct PAMData
339           **
340           **     Client data passed to PAM routines.
341           **
342           **==============================================================================
343           */
344           
345           typedef struct PAMDataStruct
346           {
347               const char* password;
348           }
349           PAMData;
350           
351           /*
352           **==============================================================================
353 kumpf 1.2 **
354           ** PAMAuthenticateCallback()
355           **
356           **     Callback used by PAMAuthenticate().
357           **
358           **==============================================================================
359           */
360           
361           static int PAMAuthenticateCallback(
362               int num_msg,
363           #if defined(PEGASUS_OS_LINUX)
364               const struct pam_message** msg,
365           #else
366               struct pam_message** msg,
367           #endif
368               struct pam_response** resp,
369               void* appdata_ptr)
370           {
371               PAMData* data = (PAMData*)appdata_ptr;
372               int i;
373           
374 kumpf 1.2     if (num_msg > 0)
375               {
376                   *resp = (struct pam_response*)calloc(
377                       num_msg, sizeof(struct pam_response));
378           
379                   if (*resp == NULL)
380                       return PAM_BUF_ERR;
381               }
382               else
383                   return PAM_CONV_ERR;
384           
385               for (i = 0; i < num_msg; i++)
386               {
387                   switch (msg[i]->msg_style)
388                   {
389                       case PAM_PROMPT_ECHO_OFF:
390                       {
391                           resp[i]->resp = (char*)malloc(PAM_MAX_MSG_SIZE);
392                           Strlcpy(resp[i]->resp, data->password, PAM_MAX_MSG_SIZE);
393                           resp[i]->resp_retcode = 0;
394                           break;
395 kumpf 1.2             }
396           
397                       default:
398                           return PAM_CONV_ERR;
399                   }
400               }
401           
402               return PAM_SUCCESS;
403           }
404           
405           /*
406           **==============================================================================
407           **
408           ** PAMValidateUserCallback()
409           **
410           **     Callback used by PAMValidateUser().
411           **
412           **==============================================================================
413           */
414           
415           static int PAMValidateUserCallback(
416 kumpf 1.2     int num_msg,
417           #if defined(PEGASUS_OS_LINUX)
418               const struct pam_message** msg,
419           #else
420               struct pam_message** msg,
421           #endif
422               struct pam_response** resp,
423               void* appdata_ptr)
424           {
425               /* Unused */
426               msg = 0;
427           
428               /* Unused */
429               appdata_ptr = 0;
430           
431               if (num_msg > 0)
432               {
433                   *resp = (struct pam_response*)calloc(
434                       num_msg, sizeof(struct pam_response));
435           
436                   if (*resp == NULL)
437 kumpf 1.2             return PAM_BUF_ERR;
438               }
439               else
440                   return PAM_CONV_ERR;
441           
442               return PAM_SUCCESS;
443           }
444           
445           /*
446           **==============================================================================
447           **
448           ** PAMAuthenticateInProcess()
449           **
450           **     Performs basic PAM authentication on the given username and password.
451           **
452           **==============================================================================
453           */
454           
455           static int PAMAuthenticateInProcess(
456               const char* username, const char* password)
457           {
458 kumpf 1.2     PAMData data;
459               struct pam_conv pconv;
460               pam_handle_t* handle;
461           
462               data.password = password;
463               pconv.conv = PAMAuthenticateCallback;
464               pconv.appdata_ptr = &data;
465           
466           
467               if (pam_start("wbem", username, &pconv, &handle) != PAM_SUCCESS)
468                   return -1;
469           
470               if (pam_authenticate(handle, 0) != PAM_SUCCESS)
471               {
472                   pam_end(handle, 0);
473                   return -1;
474               }
475           
476               if (pam_acct_mgmt(handle, 0) != PAM_SUCCESS)
477               {
478                   pam_end(handle, 0);
479 kumpf 1.2         return -1;
480               }
481           
482               pam_end(handle, 0);
483           
484               return 0;
485           }
486           
487           /*
488           **==============================================================================
489           **
490           ** PAMValidateUserInProcess()
491           **
492           **     Validate that the *username* refers to a valid PAM user.
493           **
494           **==============================================================================
495           */
496           
497           static int PAMValidateUserInProcess(const char* username)
498           {
499               PAMData data;
500 kumpf 1.2     struct pam_conv pconv;
501               pam_handle_t* phandle;
502           
503               pconv.conv = PAMValidateUserCallback;
504               pconv.appdata_ptr = &data;
505           
506               if (pam_start("wbem", username, &pconv, &phandle) != PAM_SUCCESS)
507                   return -1;
508           
509               if (pam_acct_mgmt(phandle, 0) != PAM_SUCCESS)
510               {
511                   pam_end(phandle, 0);
512                   return -1;
513               }
514           
515               pam_end(phandle, 0);
516           
517               return 0;
518           }
519           
520           /*
521 kumpf 1.2 **==============================================================================
522           **
523           ** PAMAuthenticate()
524           **
525           **     Performs basic PAM authentication on the given username and password.
526           **
527           **==============================================================================
528           */
529           
530           static int PAMAuthenticate(const char* username, const char* password)
531           {
532           #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
533               return CimserveraAuthenticate(username, password);
534           #else
535               return PAMAuthenticateInProcess(username, password);
536           #endif
537           }
538           
539           /*
540           **==============================================================================
541           **
542 kumpf 1.2 ** PAMValidateUser()
543           **
544           **     Validate that the *username* refers to a valid PAM user.
545           **
546           **==============================================================================
547           */
548           
549           static int PAMValidateUser(const char* username)
550           {
551           #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
552               return CimserveraValidateUser(username);
553           #else
554               return PAMValidateUserInProcess(username);
555           #endif
556           }
557           
558           #endif /* Executor_PAMAuth_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2