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

  1 kumpf 1.1.4.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.1.4.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.1.4.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.1.4.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.1.4.2 ** CimserveaSend()
 86               **
 87               **     Sends *size* bytes on the given socket.
 88               **
 89               **==============================================================================
 90               */
 91               
 92               static ssize_t CimserveaSend(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.1.4.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.1.4.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.1.4.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                       return -1;
160               
161                   /* Child process: */
162               
163                   if (pid == 0)
164                   {
165                       char sockStr[32];
166                       const char* argv[3];
167               
168                       close(pair[1]);
169 kumpf 1.1.4.2 
170                       /* Convert socket number to string. */
171               
172                       sprintf(sockStr, "%d", pair[0]);
173               
174                       /* Build arguments for execv(). */
175               
176                       argv[0] = CIMSERVERA;
177                       argv[1] = sockStr;
178                       argv[2] = 0;
179               
180                       /* Execute child: */
181               
182                       /* Flawfinder: ignore */
183                       execv(path, (char**)argv);
184                       close(pair[0]);
185                       _exit(0);
186                   }
187               
188                   /* Parent process: */
189               
190 kumpf 1.1.4.2     close(pair[0]);
191               
192                   *sock = pair[1];
193                   return pid;
194               }
195               
196               /*
197               **==============================================================================
198               **
199               ** CimserveraRequest
200               **
201               **==============================================================================
202               */
203               
204               typedef struct CimserveraRequestStruct
205               {
206                   char arg0[EXECUTOR_BUFFER_SIZE];
207                   char arg1[EXECUTOR_BUFFER_SIZE];
208                   char arg2[EXECUTOR_BUFFER_SIZE];
209               }
210               CimserveraRequest;
211 kumpf 1.1.4.2 
212               /*
213               **==============================================================================
214               **
215               ** CimserveraAuthenticate()
216               **
217               **==============================================================================
218               */
219               
220               static int CimserveraAuthenticate(const char* username, const char* password)
221               {
222                   int sock;
223                   int pid;
224                   int status;
225               
226                   /* Create the CIMSERVERA process. */
227               
228                   pid = CimserveraStart(&sock);
229               
230                   if (pid == -1)
231                       return -1;
232 kumpf 1.1.4.2 
233                   /* Send request, get response. */
234               
235                   status = 0;
236               
237                   do
238                   {
239                       CimserveraRequest request;
240                       int childStatus;
241               
242                       /* Send request to CIMSERVERA process. */
243               
244                       memset(&request, 0, sizeof(request));
245                       Strlcpy(request.arg0, "authenticate", EXECUTOR_BUFFER_SIZE);
246                       Strlcpy(request.arg1, username, EXECUTOR_BUFFER_SIZE);
247                       Strlcpy(request.arg2, password, EXECUTOR_BUFFER_SIZE);
248               
249                       if (CimserveaSend(sock, &request, sizeof(request)) != sizeof(request))
250                       {
251                           status = -1;
252                           break;
253 kumpf 1.1.4.2         } 
254               
255                       /* Get exist status from CIMSERVERA program. */
256               
257                       waitpid(pid, &childStatus, 0);
258               
259                       if (!WIFEXITED(childStatus) || WEXITSTATUS(childStatus) != 0)
260                       {
261                           status = -1;
262                           break;
263                       }
264                   }
265                   while (0);
266               
267                   close(sock);
268               
269                   return status;
270               }
271               
272               /*
273               **==============================================================================
274 kumpf 1.1.4.2 **
275               ** CimserveraAuthenticate()
276               **
277               **==============================================================================
278               */
279               
280               static int CimserveraValidateUser(const char* username)
281               {
282                   int sock;
283                   int pid;
284                   int status;
285               
286                   /* Create the CIMSERVERA process. */
287               
288                   pid = CimserveraStart(&sock);
289               
290                   if (pid == -1)
291                       return -1;
292               
293                   /* Send request, get response. */
294               
295 kumpf 1.1.4.2     status = 0;
296               
297                   do
298                   {
299                       CimserveraRequest request;
300                       int childStatus;
301               
302                       /* Send request to CIMSERVERA process. */
303               
304                       memset(&request, 0, sizeof(request));
305                       Strlcpy(request.arg0, "validateUser", EXECUTOR_BUFFER_SIZE);
306                       Strlcpy(request.arg1, username, EXECUTOR_BUFFER_SIZE);
307               
308                       if (CimserveaSend(sock, &request, sizeof(request)) != sizeof(request))
309                       {
310                           status = -1;
311                           break;
312                       }
313               
314                       /* Get exist status from CIMSERVERA program. */
315               
316 kumpf 1.1.4.2         waitpid(pid, &childStatus, 0);
317               
318                       if (!WIFEXITED(childStatus) || WEXITSTATUS(childStatus) != 0)
319                       {
320                           status = -1;
321                           break;
322                       }
323                   }
324                   while (0);
325               
326                   close(sock);
327               
328                   return status;
329               }
330               
331               /*
332               **==============================================================================
333               **
334               ** struct PAMData
335               **
336               **     Client data passed to PAM routines.
337 kumpf 1.1.4.2 **
338               **==============================================================================
339               */
340               
341               typedef struct PAMDataStruct
342               {
343                   const char* password;
344               }
345               PAMData;
346               
347               /*
348               **==============================================================================
349               **
350               ** PAMAuthenticateCallback()
351               **
352               **     Callback used by PAMAuthenticate().
353               **
354               **==============================================================================
355               */
356               
357               static int PAMAuthenticateCallback(
358 kumpf 1.1.4.2     int num_msg, 
359               #if defined(PEGASUS_OS_LINUX)
360                   const struct pam_message** msg,
361               #else
362                   struct pam_message** msg,
363               #endif
364                   struct pam_response** resp, 
365                   void* appdata_ptr)
366               {
367                   PAMData* data = (PAMData*)appdata_ptr;
368                   int i;
369               
370                   if (num_msg > 0)
371                   {
372                       *resp = (struct pam_response*)calloc(
373                           num_msg, sizeof(struct pam_response));
374               
375                       if (*resp == NULL) 
376                           return PAM_BUF_ERR;
377                   }
378                   else 
379 kumpf 1.1.4.2         return PAM_CONV_ERR;
380               
381                   for (i = 0; i < num_msg; i++) 
382                   {
383                       switch (msg[i]->msg_style) 
384                       {
385                           case PAM_PROMPT_ECHO_OFF:
386                           {
387                               resp[i]->resp = (char*)malloc(PAM_MAX_MSG_SIZE);
388                               Strlcpy(resp[i]->resp, data->password, PAM_MAX_MSG_SIZE);
389                               resp[i]->resp_retcode = 0;
390                               break;
391                           }
392               
393                           default:
394                               return PAM_CONV_ERR;
395                       }
396                   }
397               
398                   return PAM_SUCCESS;
399               }
400 kumpf 1.1.4.2 
401               /*
402               **==============================================================================
403               **
404               ** PAMValidateUserCallback()
405               **
406               **     Callback used by PAMValidateUser().
407               **
408               **==============================================================================
409               */
410               
411               static int PAMValidateUserCallback(
412                   int num_msg, 
413               #if defined(PEGASUS_OS_LINUX)
414                   const struct pam_message** msg,
415               #else
416                   struct pam_message** msg,
417               #endif
418                   struct pam_response** resp, 
419                   void* appdata_ptr)
420               {
421 kumpf 1.1.4.2     /* Unused */
422                   msg = 0;
423               
424                   /* Unused */
425                   appdata_ptr = 0;
426               
427                   if (num_msg > 0)
428                   {
429                       *resp = (struct pam_response*)calloc(
430                           num_msg, sizeof(struct pam_response));
431               
432                       if (*resp == NULL)
433                           return PAM_BUF_ERR;
434                   }
435                   else
436                       return PAM_CONV_ERR;
437               
438                   return PAM_SUCCESS;
439               }
440               
441               /*
442 kumpf 1.1.4.2 **==============================================================================
443               **
444               ** PAMAuthenticateInProcess()
445               **
446               **     Peforms basic PAM authentication on the given username and password.
447               **
448               **==============================================================================
449               */
450               
451               static int PAMAuthenticateInProcess(
452                   const char* username, const char* password)
453               {
454                   PAMData data;
455                   struct pam_conv pconv;
456                   pam_handle_t* handle;
457               
458                   data.password = password;
459                   pconv.conv = PAMAuthenticateCallback;
460                   pconv.appdata_ptr = &data;
461               
462               
463 kumpf 1.1.4.2     if (pam_start("wbem", username, &pconv, &handle) != PAM_SUCCESS)
464                       return -1;
465               
466                   if (pam_authenticate(handle, 0) != PAM_SUCCESS) 
467                   {
468                       pam_end(handle, 0);
469                       return -1;
470                   }
471               
472                   if (pam_acct_mgmt(handle, 0) != PAM_SUCCESS) 
473                   {
474                       pam_end(handle, 0);
475                       return -1;
476                   }
477               
478                   pam_end(handle, 0);
479               
480                   return 0;
481               }
482               
483               /*
484 kumpf 1.1.4.2 **==============================================================================
485               **
486               ** PAMValidateUserInProcess()
487               **
488               **     Validate that the *username* refers to a valid PAM user.
489               **
490               **==============================================================================
491               */
492               
493               static int PAMValidateUserInProcess(const char* username)
494               {
495                   PAMData data;
496                   struct pam_conv pconv;
497                   pam_handle_t* phandle;
498               
499                   pconv.conv = PAMValidateUserCallback;
500                   pconv.appdata_ptr = &data;
501               
502                   if (pam_start("wbem", username, &pconv, &phandle) != PAM_SUCCESS)
503                       return -1;
504               
505 kumpf 1.1.4.2     if (pam_acct_mgmt(phandle, 0) != PAM_SUCCESS)
506                   {
507                       pam_end(phandle, 0);
508                       return -1;
509                   }
510               
511                   pam_end(phandle, 0);
512               
513                   return 0;
514               }
515               
516               /*
517               **==============================================================================
518               **
519               ** PAMAuthenticate()
520               **
521               **     Peforms basic PAM authentication on the given username and password.
522               **
523               **==============================================================================
524               */
525               
526 kumpf 1.1.4.2 static int PAMAuthenticate(const char* username, const char* password)
527               {
528               #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
529                   return CimserveraAuthenticate(username, password);
530               #else
531                   return PAMAuthenticateInProcess(username, password);
532               #endif
533               }
534               
535               /*
536               **==============================================================================
537               **
538               ** PAMValidateUser()
539               **
540               **     Validate that the *username* refers to a valid PAM user.
541               **
542               **==============================================================================
543               */
544               
545               static int PAMValidateUser(const char* username)
546               {
547 kumpf 1.1.4.2 #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
548                   return CimserveraValidateUser(username);
549               #else
550                   return PAMValidateUserInProcess(username);
551               #endif
552               }
553               
554               #endif /* Executor_PAMAuth_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2