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

  1 mike  1.1.2.1 /*
  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 mike  1.1.2.1 // 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 mike  1.1.2.1 #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               #define CIMSERVERA "cimservera"
 56               
 57               /*
 58               **==============================================================================
 59               **
 60               ** cimservera
 61               **
 62               **     This program is used to authenticate users with the "Basic PAM 
 63               **     Authentication" scheme. It was originally written to isolate memory
 64 mike  1.1.2.1 **     PAM module errors to an external process.
 65               **
 66               **     This header defines two functions that may be called by clients of this
 67               **     process (the parent process).
 68               **
 69               **         CimserveraAuthenticate()
 70               **         CimserveraValidateUser()
 71               **
 72               **     Each functions forks and executes a child process that carries out
 73               **     the request and then exits immediately. The parent and child proceses
 74               **     communicate over a local domain socket, created by the parent just
 75               **     before executing the client program.
 76               **
 77               **     Both of the functions above are defined in the header to avoid the need
 78               **     to link a separate client library.
 79               **
 80               **     CAUTION: This program must not depend on any Pegasus libraries since
 81               **     it is used by the executor process.
 82               **
 83               **==============================================================================
 84               */
 85 mike  1.1.2.1 
 86               /*
 87               **==============================================================================
 88               **
 89               ** CimserveaSend()
 90               **
 91               **     Sends *size* bytes on the given socket.
 92               **
 93               **==============================================================================
 94               */
 95               
 96               static ssize_t CimserveaSend(int sock, void* buffer, size_t size)
 97               {
 98                   size_t r = size;
 99                   char* p = (char*)buffer;
100               
101                   while (r)
102                   {
103                       ssize_t n;
104                       EXECUTOR_RESTART(write(sock, p, r), n);
105               
106 mike  1.1.2.1         if (n == -1)
107                           return -1;
108                       else if (n == 0)
109                           return size - r;
110               
111                       r -= n;
112                       p += n;
113                   }
114               
115                   return size - r;
116               }
117               
118               /*
119               **==============================================================================
120               **
121               ** CimserveraStart()
122               **
123               **     Starts the cimservera program, returning a socket used to communicate
124               **     with it.
125               **
126               **==============================================================================
127 mike  1.1.2.1 */
128               
129               static int CimserveraStart(int* sock)
130               {
131                   int pair[2];
132                   int pid;
133               
134                   /* Get absolute path of "cimservera" program. */
135               
136                   char path[EXECUTOR_BUFFER_SIZE];
137               
138                   if (PEGASUS_PAM_STANDALONE_PROC_NAME[0] == '/')
139                       Strlcpy(path, PEGASUS_PAM_STANDALONE_PROC_NAME, EXECUTOR_BUFFER_SIZE);
140                   else
141                   {
142                       /* Flawfinder: ignore */
143                       const char* home = getenv("PEGASUS_HOME");
144               
145                       if (!home)
146                           return -1;
147               
148 mike  1.1.2.1         Strlcpy(path, home, EXECUTOR_BUFFER_SIZE);
149                       Strlcat(path, "/", EXECUTOR_BUFFER_SIZE);
150                       Strlcat(path, PEGASUS_PAM_STANDALONE_PROC_NAME, EXECUTOR_BUFFER_SIZE);
151                   }
152               
153                   /* Create socket pair for communicating with child process. */
154               
155                   if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) != 0)
156                       return -1;
157               
158                   /* Fork child: */
159               
160                   pid = fork();
161               
162                   if (pid < 0)
163                       return -1;
164               
165                   /* Child process: */
166               
167                   if (pid == 0)
168                   {
169 mike  1.1.2.1         char sockStr[32];
170                       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               
186                       /* Flawfinder: ignore */
187                       execv(path, argv);
188                       close(pair[0]);
189                       _exit(0);
190 mike  1.1.2.1     }
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               */
207               
208               typedef struct CimserveraRequestStruct
209               {
210                   char arg0[EXECUTOR_BUFFER_SIZE];
211 mike  1.1.2.1     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                   int pid;
228                   int status;
229               
230                   /* Create the CIMSERVERA process. */
231               
232 mike  1.1.2.1     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                       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 mike  1.1.2.1         if (CimserveaSend(sock, &request, sizeof(request)) != sizeof(request))
254                       {
255                           status = -1;
256                           break;
257                       } 
258               
259                       /* Get exist 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                   while (0);
270               
271                   close(sock);
272               
273                   return status;
274 mike  1.1.2.1 }
275               
276               /*
277               **==============================================================================
278               **
279               ** CimserveraAuthenticate()
280               **
281               **==============================================================================
282               */
283               
284               static int CimserveraValidateUser(const char* username)
285               {
286                   int sock;
287                   int pid;
288                   int status;
289               
290                   /* Create the CIMSERVERA process. */
291               
292                   pid = CimserveraStart(&sock);
293               
294                   if (pid == -1)
295 mike  1.1.2.1         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               
312                       if (CimserveaSend(sock, &request, sizeof(request)) != sizeof(request))
313                       {
314                           status = -1;
315                           break;
316 mike  1.1.2.1         }
317               
318                       /* Get exist 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                   return status;
333               }
334               
335               /*
336               **==============================================================================
337 mike  1.1.2.1 **
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               **
354               ** PAMAuthenticateCallback()
355               **
356               **     Callback used by PAMAuthenticate().
357               **
358 mike  1.1.2.1 **==============================================================================
359               */
360               
361               static int PAMAuthenticateCallback(
362                   int num_msg, 
363                   const struct pam_message** msg,
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 mike  1.1.2.1         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 mike  1.1.2.1 
401               /*
402               **==============================================================================
403               **
404               ** PAMValidateUserCallback()
405               **
406               **     Callback used by PAMValidateUser().
407               **
408               **==============================================================================
409               */
410               
411               static int PAMValidateUserCallback(
412                   int num_msg, 
413                   const struct pam_message** msg,
414                   struct pam_response** resp, 
415                   void* appdata_ptr)
416               {
417                   if (num_msg > 0)
418                   {
419                       *resp = (struct pam_response*)calloc(
420                           num_msg, sizeof(struct pam_response));
421 mike  1.1.2.1 
422                       if (*resp == NULL)
423                           return PAM_BUF_ERR;
424                   }
425                   else
426                       return PAM_CONV_ERR;
427               
428                   return PAM_SUCCESS;
429               }
430               
431               /*
432               **==============================================================================
433               **
434               ** PAMAuthenticateInProcess()
435               **
436               **     Peforms basic PAM authentication on the given username and password.
437               **
438               **==============================================================================
439               */
440               
441               static int PAMAuthenticateInProcess(const char* username, const char* password)
442 mike  1.1.2.1 {
443                   PAMData data;
444                   struct pam_conv pconv;
445                   pam_handle_t* handle;
446               
447                   data.password = password;
448                   pconv.conv = PAMAuthenticateCallback;
449                   pconv.appdata_ptr = &data;
450               
451               
452                   if (pam_start("wbem", username, &pconv, &handle) != PAM_SUCCESS)
453                       return -1;
454               
455                   if (pam_authenticate(handle, 0) != PAM_SUCCESS) 
456                   {
457                       pam_end(handle, 0);
458                       return -1;
459                   }
460               
461                   if (pam_acct_mgmt(handle, 0) != PAM_SUCCESS) 
462                   {
463 mike  1.1.2.1         pam_end(handle, 0);
464                       return -1;
465                   }
466               
467                   pam_end(handle, 0);
468               
469                   return 0;
470               }
471               
472               /*
473               **==============================================================================
474               **
475               ** PAMValidateUserInProcess()
476               **
477               **     Validate that the *username* refers to a valid PAM user.
478               **
479               **==============================================================================
480               */
481               
482               static int PAMValidateUserInProcess(const char* username)
483               {
484 mike  1.1.2.1     PAMData data;
485                   struct pam_conv pconv;
486                   pam_handle_t* phandle;
487               
488                   pconv.conv = PAMValidateUserCallback;
489                   pconv.appdata_ptr = &data;
490               
491                   if (pam_start("wbem", username, &pconv, &phandle) != PAM_SUCCESS)
492                       return -1;
493               
494                   if (pam_acct_mgmt(phandle, 0) != PAM_SUCCESS)
495                   {
496                       pam_end(phandle, 0);
497                       return -1;
498                   }
499               
500                   pam_end(phandle, 0);
501               
502                   return 0;
503               }
504               
505 mike  1.1.2.1 /*
506               **==============================================================================
507               **
508               ** PAMAuthenticate()
509               **
510               **     Peforms basic PAM authentication on the given username and password.
511               **
512               **==============================================================================
513               */
514               
515               static int PAMAuthenticate(const char* username, const char* password)
516               {
517               #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
518                   return CimserveraAuthenticate(username, password);
519               #else
520                   return PAMAuthenticateInProcess(username, password);
521               #endif
522               }
523               
524               /*
525               **==============================================================================
526 mike  1.1.2.1 **
527               ** PAMValidateUser()
528               **
529               **     Validate that the *username* refers to a valid PAM user.
530               **
531               **==============================================================================
532               */
533               
534               static int PAMValidateUser(const char* username)
535               {
536               #ifdef PEGASUS_USE_PAM_STANDALONE_PROC
537                   return CimserveraValidateUser(username);
538               #else
539                   return PAMValidateUserInProcess(username);
540               #endif
541               }
542               
543               #endif /* Executor_PAMAuth_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2