source: TI12-security/trunk/NDGSecurity/C/pam_oci8.c @ 6630

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/C/pam_oci8.c@6630
Revision 6630, 9.1 KB checked in by pjkersha, 10 years ago (diff)

Keep a record of work on this PAM plugin for Oracle - May be required for MyProxy? CA deployments where Oracle is the native user db.

Line 
1/***************************************************************************
2
3                         * PAM module for Oracle, OCi8, ported from pam_mysql *
4                         * written by: Andreas Kofler <andreas.kofler@gmx.net> *
5
6
7                             -------------------
8    copyright            : (C) 2002 by Siag, Andreas Kofler
9    email                : Andreas Kofler <andreas.kofler@gmx.net>
10 ***************************************************************************/
11/***************************************************************************
12 *                                                                         *
13 *   This program is free software; you can redistribute it and/or modify  *
14 *   it under the terms of the GNU General Public License as published by  *
15 *   the Free Software Foundation; either version 2 of the License, or     *
16 *   (at your option) any later version.                                   *
17 *                                                                         *
18 ***************************************************************************/
19
20
21#define _GNU_SOURCE
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <syslog.h>
27#include <stdarg.h>
28#include <alloca.h>
29#include <string.h>
30#include "sqlora.h"
31
32/*
33 * here, we make definitions for the externally accessible functions
34 * in this file (these definitions are required for static modules
35 * but strongly encouraged generally) they are used to instruct the
36 * modules include file to define their prototypes.
37 */
38
39#define PAM_SM_AUTH
40#define PAM_SM_ACCOUNT
41#define PAM_SM_SESSION
42#define PAM_SM_PASSWORD
43
44#define PAM_MODULE_NAME  "pam_oci8"
45#define PLEASE_ENTER_PASSWORD "Password:"
46/* #define DEBUG */
47
48#include <security/pam_modules.h>
49#include <security/pam_misc.h>
50
51struct optionstruct {
52        char where[257];
53        char connectString[65];
54        char table[17];
55        char usercolumn[17];
56        char passwdcolumn[17];
57};
58
59
60/* Global Variables */
61
62sqlo_db_handle_t dbh;
63int connected=0;
64
65struct optionstruct options =
66{
67        "",
68        "user/password@host",
69        "TABLE",
70        "USERCOLUMN",
71        "PASSWDCOLUMN",
72};
73
74/* Prototypes */
75int converse (pam_handle_t * pamh, int nargs, struct pam_message **message, struct pam_response **response);
76int _set_auth_tok (pam_handle_t * pamh, int flags, int argc, const char **argv);
77
78/*int db_connect (sqlo_db_handle_t dbh);*/
79int db_connect ();
80void db_close( void );
81int askForPassword(pam_handle_t *pamh);
82
83void db_close ( void ){
84        if (connected) {
85                connected=0;
86                sqlo_finish(dbh);
87        }
88}
89
90/* sqlora access functions */
91int db_connect (){
92        connected=0;
93  if (SQLO_SUCCESS != sqlo_init(SQLO_OFF, 1, 100)) {
94    syslog(LOG_ERR, "pam_oci8: Failed to init libsqlora8\n");
95    return PAM_AUTH_ERR;
96  }
97
98        /* login */
99  if (SQLO_SUCCESS != sqlo_connect(&dbh, options.connectString)) {
100        syslog(LOG_ERR, "pam_oci8: Cannot login with %s\n", options.connectString);
101    return PAM_AUTH_ERR;
102  }
103        connected=1;
104  return PAM_SUCCESS;
105}
106
107static int db_checkpasswd (const char *user, const char *passwd){
108        sqlo_stmt_handle_t sth;
109        int retval;
110        char *sql = (char * )malloc (100 + strlen (user) + strlen (passwd) +
111                                                        strlen (options.table) + 2*strlen (options.usercolumn) +
112                                                        strlen (options.passwdcolumn) + strlen (options.where));
113
114        sprintf(sql, "SELECT %s FROM %s WHERE %s='%s' and %s='%s' %s",
115                                options.usercolumn, options.table, options.usercolumn,
116                                user, options.passwdcolumn, passwd, options.where);
117
118  if ( 0 > (sth = (sqlo_open(dbh, sql, 0, 0))) ) {
119                syslog(LOG_ERR, "pam_oci8: Sql-error: %s", sql);
120                free(sql);
121                return PAM_AUTH_ERR;
122        }
123
124        if ( SQLO_SUCCESS == (sqlo_fetch(sth, 1))) {
125                /*if the sql-query returns a ruslt --> authentication was successfully*/
126                retval=PAM_SUCCESS;
127        }
128        else {
129                syslog(LOG_ERR, "pam_oci8: Authentication failure, user %s", user);
130                retval=PAM_AUTH_ERR;
131        }
132        free(sql);
133        sqlo_close(sth);
134        return retval;
135}
136
137
138/* Global PAM functions stolen from other modules */
139
140int converse(pam_handle_t *pamh, int nargs
141                    , struct pam_message **message
142                    , struct pam_response **response)
143{
144    int retval;
145    struct pam_conv *conv;
146
147    retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
148    if ( retval == PAM_SUCCESS )
149    {
150        retval = conv->conv(nargs, ( const struct pam_message ** ) message
151                            , response, conv->appdata_ptr);
152        if ((retval != PAM_SUCCESS) && (retval != PAM_CONV_AGAIN))
153        {
154            syslog(LOG_DEBUG, "pam_oci8: conversation failure [%s]"
155                     , pam_strerror(pamh, retval));
156        }
157    }
158    else
159    {
160        syslog(LOG_ERR, "pam_oci8: couldn't obtain coversation function [%s]"
161                 , pam_strerror(pamh, retval));
162    }
163    return retval;                  /* propagate error status */
164}
165
166int askForPassword(pam_handle_t *pamh)
167{
168        struct pam_message msg[1], *mesg[1];
169        struct pam_response *resp=NULL;
170        char *prompt=NULL;
171        int i=0;
172        int retval;
173
174        prompt = malloc(strlen(PLEASE_ENTER_PASSWORD));
175        if (prompt == NULL)
176        {
177                syslog(LOG_ERR,"pam_oci8: askForPassword(), out of memory!?");
178                return PAM_BUF_ERR;
179        }
180        else
181        {
182                sprintf(prompt, PLEASE_ENTER_PASSWORD);
183                msg[i].msg = prompt;
184        }
185        msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
186        mesg[i] = &msg[i];
187
188        retval = converse(pamh, ++i, mesg, &resp);
189        if (prompt)
190        {
191            _pam_overwrite(prompt);
192            _pam_drop(prompt);
193        }
194        if (retval != PAM_SUCCESS)
195        {
196            if (resp != NULL)
197                _pam_drop_reply(resp,i);
198            return ((retval == PAM_CONV_AGAIN)
199                    ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL);
200        }
201
202        /* we have a password so set AUTHTOK
203         */
204        return pam_set_item(pamh, PAM_AUTHTOK, resp->resp);
205}
206
207
208/* PAM Authentication functions */
209
210PAM_EXTERN int pam_sm_authenticate (pam_handle_t * pamh,
211                                    int flags,
212                                    int argc,
213                                    const char **argv)
214{
215        int retval, i;
216        const char *user;
217        char *passwd = NULL;
218/*      MYSQL auth_sql_server;*/
219
220#ifdef DEBUG
221        D (("called."));
222#endif
223
224/* Parse arguments taken from pam_listfile.c */
225        for (i = 0; i < argc; i++) {
226                char *junk;
227                char mybuf[256], myval[256];
228
229                junk = (char *) malloc (strlen (argv[i]) + 1);
230                if (junk == NULL) {
231#ifdef DEBUG
232                        D (("returning PAM_BUF_ERR."));
233                        return PAM_BUF_ERR;
234#endif
235                }
236                strcpy (junk, argv[i]);
237                if ((strchr (junk, (int) '=') != NULL)) {
238                        strncpy (mybuf, strtok (junk, "="), 255);
239                        strncpy (myval, strtok (NULL, "="), 255);
240                        free (junk);
241                        if (!strcasecmp ("where", mybuf)) {
242                                strncpy (options.where, myval, 256);
243                                D (("where changed."));
244#ifdef DEBUG
245                                syslog(LOG_ERR, "pam_oci8: where now is %s", options.where);
246#endif
247                        } else if (!strcasecmp ("connectString", mybuf)) {
248                                strncpy (options.connectString, myval, 64);
249                                D (("connectString changed."));
250                        } else if (!strcasecmp ("table", mybuf)) {
251                                strncpy (options.table, myval, 16);
252                                D (("table changed."));
253                        } else if (!strcasecmp ("usercolumn", mybuf)) {
254                                strncpy (options.usercolumn, myval, 16);
255                                D (("usercolumn changed."));
256                        } else if (!strcasecmp ("passwdcolumn", mybuf)) {
257                                strncpy (options.passwdcolumn, myval, 16);
258                                D (("passwdcolumn changed."));
259                        }
260                }
261        }/* for loop */
262
263        /* Get User */
264
265        retval = pam_get_user (pamh, &user, NULL);
266        if (retval != PAM_SUCCESS || user == NULL) {
267                syslog (LOG_ERR, "pam_oci8: no user specified");
268                return PAM_USER_UNKNOWN;
269        }
270
271        retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &passwd);
272        if ( passwd == NULL )
273        {
274                askForPassword(pamh);
275        }
276        retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&passwd);
277
278        if ( passwd == NULL )
279                return PAM_AUTHINFO_UNAVAIL;
280
281        if ((retval = db_connect ()) != PAM_SUCCESS) {
282                db_close();
283                D (("returning %i after db_connect.",retval));
284                return retval;
285        }
286        if ((retval = db_checkpasswd (user, passwd)) != PAM_SUCCESS) {
287                D (("returning %i after db_checkpasswd.",retval));
288                db_close();
289                return retval;
290        }
291#ifdef DEBUG
292        D (("returning %i.",retval));
293#endif
294        db_close();
295        return retval;
296
297}/* pam_sm_authenticate */
298
299
300/* --- account management functions --- */
301PAM_EXTERN int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, int argc
302                                 ,const char **argv)
303{
304#ifdef DEBUG
305        syslog (LOG_INFO, "pam_oci8: acct_mgmt called but not implemented. Dont panic though :)");
306#endif
307        return PAM_SUCCESS;
308}
309
310PAM_EXTERN
311int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
312                   ,const char **argv)
313{
314#ifdef DEBUG
315     syslog(LOG_INFO, "pam_oci8: setcred called but not implemented.");
316#endif
317     return PAM_SUCCESS;
318}
319
320/* --- password management --- */
321
322PAM_EXTERN
323int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc
324                     ,const char **argv)
325{
326     syslog(LOG_INFO, "pam_oci8: chauthtok called but not implemented. Password NOT CHANGED!");
327     return PAM_SUCCESS;
328}
329
330/* --- session management --- */
331
332PAM_EXTERN
333int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc
334                        ,const char **argv)
335{
336#ifdef DEBUG
337     syslog(LOG_INFO, "pam_oci8: open_session called but not implemented.");
338#endif
339    return PAM_SUCCESS;
340}
341
342PAM_EXTERN
343int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc
344                         ,const char **argv)
345{
346     syslog(LOG_INFO, "pam_oci8: close_session called but not implemented.");
347     return PAM_SUCCESS;
348}
349
350/* end of module definition */
351
352#ifdef PAM_STATIC
353
354/* static module data */
355
356struct pam_module _pam_permit_modstruct = {
357    "pam_permit",
358    pam_sm_authenticate,
359    pam_sm_setcred,
360    pam_sm_acct_mgmt,
361    pam_sm_open_session,
362    pam_sm_close_session,
363    pam_sm_chauthtok
364};
365
366#endif
Note: See TracBrowser for help on using the repository browser.