[PATCH] Add PAM session support
Andrew Bartlett
abartlet at pcug.org.au
Wed Apr 18 02:39:57 GMT 2001
This patch adds PAM session support to samba, in much the same way that
utmp support was added. I understand that this is not an ideal
implementation, but its what I know works.
If people have any ideas on a better implementation, feel free to
comment :-)
This patch also cleans up the arguments to claim_connection(), as the
last 2 are not used anymore.
Andrew Bartlett
abartlet at pcug.org.au
--
Andrew Bartlett
abartlet at pcug.org.au
-------------- next part --------------
Index: source/smbd/connection.c
===================================================================
RCS file: /cvsroot/samba/source/smbd/connection.c,v
retrieving revision 1.20.4.7
diff -u -r1.20.4.7 connection.c
--- source/smbd/connection.c 2001/04/08 20:22:54 1.20.4.7
+++ source/smbd/connection.c 2001/04/18 00:41:59
@@ -28,10 +28,36 @@
extern int DEBUGLEVEL;
#ifdef WITH_UTMP
-static void utmp_yield(pid_t pid, const connection_struct *conn);
-static void utmp_claim(const struct connections_data *crec, const connection_struct *conn);
+static BOOL utmp_yield(pid_t pid, const connection_struct *conn);
+static BOOL utmp_claim(const struct connections_data *crec, const connection_struct *conn);
#endif
+#ifdef WITH_PAM
+static BOOL claim_pam(const connection_struct *conn);
+static BOOL yield_pam(const connection_struct *conn);
+#endif
+#if defined(WITH_UTMP) || defined(WITH_PAM)
+static int cnum_claim_tdb(const connection_struct *conn);
+static int cnum_yield_tdb(const connection_struct *conn);
+static int cnum_fetch_tdb(const connection_struct *conn);
+
+/* This is also used with the PAM 'tty' so I moved it up here
+ - Andrew Bartlett */
+/*
+ * ut_line:
+ * size small, e.g. Solaris: 12; FreeBSD: 8
+ * pattern conventions differ across systems.
+ * So take care in tweaking the template below.
+ * Arguably, this could be yet another smb.conf parameter.
+ */
+static const char *ut_line_template =
+#if defined(__FreeBSD__)
+ "smb%d" ;
+#else
+ "smb/%d" ;
+#endif
+#endif
+
/****************************************************************************
Return the connection tdb context (used for message send all).
****************************************************************************/
@@ -49,6 +75,8 @@
struct connections_key key;
TDB_DATA kbuf;
+ BOOL ret = True;
+
if (!tdb) return False;
DEBUG(3,("Yielding connection to %s\n",name));
@@ -68,27 +96,41 @@
if(conn)
utmp_yield(key.pid, conn);
#endif
+
+#ifdef WITH_PAM
+ if(conn)
+ ret = yield_pam(conn);
+#else
+ ret = True;
+#endif
+
+#if defined(WITH_UTMP) || defined(WITH_PAM)
+ if (conn)
+ cnum_yield_tdb(conn);
+#endif
- return(True);
+ return ret;
}
/****************************************************************************
claim an entry in the connections database
****************************************************************************/
-BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear)
+BOOL claim_connection(connection_struct *conn,char *name)
{
struct connections_key key;
struct connections_data crec;
TDB_DATA kbuf, dbuf;
+ BOOL ret = False;
+
if (!tdb) {
tdb = tdb_open(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST,
O_RDWR | O_CREAT, 0644);
}
if (!tdb) return False;
- DEBUG(5,("claiming %s %d\n",name,max_connections));
+ DEBUG(5,("claiming connection for %s\n",name));
ZERO_STRUCT(key);
key.pid = sys_getpid();
@@ -120,13 +162,183 @@
if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) return False;
-#ifdef WITH_UTMP
+#if defined(WITH_UTMP) || defined(WITH_PAM)
if (conn)
+ if (cnum_claim_tdb(conn) == -1)
+ return False;
+#endif
+
+#ifdef WITH_PAM
+ if(conn)
+ ret = claim_pam(conn);
+#else
+ ret = True;
+#endif
+
+
+#ifdef WITH_UTMP
+ if (conn && ret)
utmp_claim(&crec, conn);
#endif
- return True;
+ return ret;
+}
+
+#if defined(WITH_UTMP) || defined(WITH_PAM)
+/****************************************************************************
+obtain/release a small number (0 upwards) unique within and across smbds
+****************************************************************************/
+/*
+ * Need a "small" number to represent this connection, unique within this
+ * smbd and across all smbds.
+ *
+ * claim:
+ * Start at 0, hunt up for free, unique number "unum" by attempting to
+ * store it as a key in a tdb database:
+ * key: unum data: pid+conn
+ * Also store its inverse, ready for yield function:
+ * key: pid+conn data: unum
+ *
+ * yield:
+ * Find key: pid+conn; data is unum; delete record
+ * Find key: unum ; delete record.
+ *
+ * Comment:
+ * The claim algorithm (a "for" loop attempting to store numbers in a tdb
+ * database) will be increasingly inefficient with larger numbers of
+ * connections. Is it possible to write a suitable primitive within tdb?
+ *
+ * However, by also storing the inverse key/data pair, we at least make
+ * the yield algorithm efficient.
+ */
+
+static TDB_CONTEXT *tdb_cnum;
+
+struct cnum_tdb_data {
+ pid_t pid;
+ int cnum;
+};
+
+static int cnum_claim_tdb(const connection_struct *conn)
+{
+ struct cnum_tdb_data udata;
+ int i, slotnum;
+ TDB_DATA kbuf, dbuf;
+
+ if (!tdb_cnum) {
+ tdb_cnum = tdb_open(lock_path("cnum.tdb"), 0,
+ TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644);
+ }
+ if (!tdb_cnum) return(-1);
+
+ DEBUG(2,("cnum_claim_tdb: entered\n"));
+
+ ZERO_STRUCT(udata);
+ udata.pid = sys_getpid();
+ udata.cnum = conn ? conn->cnum : -1;
+
+ dbuf.dptr = (char *) &udata;
+ dbuf.dsize = sizeof(udata);
+
+ /* The key is simply a number as close as possible to zero: find it */
+ slotnum = -1;
+ /* stop loop when overflow +ve integers (a huge, busy machine!) */
+ for (i = 0; i >= 0 ; i++) {
+ kbuf.dptr = (char *) &i;
+ kbuf.dsize = sizeof(i);
+
+ if (tdb_store(tdb_cnum, kbuf, dbuf, TDB_INSERT) == 0) {
+ /* have successfully grabbed a free slot */
+ slotnum = i;
+
+ /* store the inverse for faster cnum_yield_tdb() */
+ tdb_store(tdb_cnum, dbuf, kbuf, TDB_INSERT);
+
+ break; /* Got it; escape */
+ }
+ }
+ if (slotnum < 0) { /* more connections than positive integers! */
+ DEBUG(2,("cnum_claim_tdb: failed\n"));
+ return(-1);
+ }
+
+ DEBUG(2,("cnum_claim_tdb: leaving with %d\n", slotnum));
+
+ return(slotnum);
+}
+
+static int cnum_yield_tdb(const connection_struct *conn)
+{
+ struct cnum_tdb_data revkey;
+ int slotnum;
+ TDB_DATA kbuf, dbuf;
+
+ if (!tdb_cnum) {
+ return(-1);
+ }
+
+ DEBUG(2,("cnum_yield_tdb: entered\n"));
+
+ ZERO_STRUCT(revkey);
+ revkey.pid = sys_getpid();
+ revkey.cnum = conn ? conn->cnum : -1;
+
+ kbuf.dptr = (char *) &revkey;
+ kbuf.dsize = sizeof(revkey);
+
+ dbuf = tdb_fetch(tdb_cnum, kbuf);
+ if (dbuf.dptr == NULL) {
+ DEBUG(2,("cnum_yield_tdb: failed\n"));
+ return(-1); /* shouldn't happen */
+ }
+
+ /* Save our result */
+ slotnum = *((int*)dbuf.dptr);
+
+ /* Tidy up */
+ tdb_delete(tdb_cnum, kbuf);
+ tdb_delete(tdb_cnum, dbuf);
+
+ free(dbuf.dptr);
+ DEBUG(2,("cnum_yield_tdb: leaving with %d\n", slotnum));
+
+ return(slotnum);
+}
+
+static int cnum_fetch_tdb(const connection_struct *conn)
+{
+ struct cnum_tdb_data revkey;
+ int slotnum;
+ TDB_DATA kbuf, dbuf;
+
+ if (!tdb_cnum) {
+ return(-1);
+ }
+
+ DEBUG(2,("cnum_fetch_tdb: entered\n"));
+
+ ZERO_STRUCT(revkey);
+ revkey.pid = sys_getpid();
+ revkey.cnum = conn ? conn->cnum : -1;
+
+ kbuf.dptr = (char *) &revkey;
+ kbuf.dsize = sizeof(revkey);
+
+ dbuf = tdb_fetch(tdb_cnum, kbuf);
+ if (dbuf.dptr == NULL) {
+ DEBUG(2,("cnum_fetch_tdb: failed\n"));
+ return(-1); /* shouldn't happen */
+ }
+
+ /* Save our result */
+ slotnum = *((int*)dbuf.dptr);
+
+ free(dbuf.dptr);
+ DEBUG(2,("cnum_fetch_tdb: leaving with %d\n", slotnum));
+
+ return(slotnum);
}
+#endif
#ifdef WITH_UTMP
@@ -232,126 +444,6 @@
#include <lastlog.h>
#endif
-/****************************************************************************
-obtain/release a small number (0 upwards) unique within and across smbds
-****************************************************************************/
-/*
- * Need a "small" number to represent this connection, unique within this
- * smbd and across all smbds.
- *
- * claim:
- * Start at 0, hunt up for free, unique number "unum" by attempting to
- * store it as a key in a tdb database:
- * key: unum data: pid+conn
- * Also store its inverse, ready for yield function:
- * key: pid+conn data: unum
- *
- * yield:
- * Find key: pid+conn; data is unum; delete record
- * Find key: unum ; delete record.
- *
- * Comment:
- * The claim algorithm (a "for" loop attempting to store numbers in a tdb
- * database) will be increasingly inefficient with larger numbers of
- * connections. Is it possible to write a suitable primitive within tdb?
- *
- * However, by also storing the inverse key/data pair, we at least make
- * the yield algorithm efficient.
- */
-
-static TDB_CONTEXT *tdb_utmp;
-
-struct utmp_tdb_data {
- pid_t pid;
- int cnum;
-};
-
-static int utmp_claim_tdb(const connection_struct *conn)
-{
- struct utmp_tdb_data udata;
- int i, slotnum;
- TDB_DATA kbuf, dbuf;
-
- if (!tdb_utmp) {
- tdb_utmp = tdb_open(lock_path("utmp.tdb"), 0,
- TDB_CLEAR_IF_FIRST, O_RDWR | O_CREAT, 0644);
- }
- if (!tdb_utmp) return(-1);
-
- DEBUG(2,("utmp_claim_tdb: entered\n"));
-
- ZERO_STRUCT(udata);
- udata.pid = sys_getpid();
- udata.cnum = conn ? conn->cnum : -1;
-
- dbuf.dptr = (char *) &udata;
- dbuf.dsize = sizeof(udata);
-
- /* The key is simply a number as close as possible to zero: find it */
- slotnum = -1;
- /* stop loop when overflow +ve integers (a huge, busy machine!) */
- for (i = 0; i >= 0 ; i++) {
- kbuf.dptr = (char *) &i;
- kbuf.dsize = sizeof(i);
-
- if (tdb_store(tdb_utmp, kbuf, dbuf, TDB_INSERT) == 0) {
- /* have successfully grabbed a free slot */
- slotnum = i;
-
- /* store the inverse for faster utmp_yield_tdb() */
- tdb_store(tdb_utmp, dbuf, kbuf, TDB_INSERT);
-
- break; /* Got it; escape */
- }
- }
- if (slotnum < 0) { /* more connections than positive integers! */
- DEBUG(2,("utmp_claim_tdb: failed\n"));
- return(-1);
- }
-
- DEBUG(2,("utmp_claim_tdb: leaving with %d\n", slotnum));
-
- return(slotnum);
-}
-
-static int utmp_yield_tdb(const connection_struct *conn)
-{
- struct utmp_tdb_data revkey;
- int i, slotnum;
- TDB_DATA kbuf, dbuf;
-
- if (!tdb_utmp) {
- return(-1);
- }
-
- DEBUG(2,("utmp_yield_tdb: entered\n"));
-
- ZERO_STRUCT(revkey);
- revkey.pid = sys_getpid();
- revkey.cnum = conn ? conn->cnum : -1;
-
- kbuf.dptr = (char *) &revkey;
- kbuf.dsize = sizeof(revkey);
-
- dbuf = tdb_fetch(tdb_utmp, kbuf);
- if (dbuf.dptr == NULL) {
- DEBUG(2,("utmp_yield_tdb: failed\n"));
- return(-1); /* shouldn't happen */
- }
-
- /* Save our result */
- slotnum = *((int*) dbuf.dptr);
-
- /* Tidy up */
- tdb_delete(tdb_utmp, kbuf);
- tdb_delete(tdb_utmp, dbuf);
-
- free(dbuf.dptr);
- DEBUG(2,("utmp_yield_tdb: leaving with %d\n", slotnum));
-
- return(slotnum);
-}
-
#if defined(HAVE_UT_UT_ID)
/****************************************************************************
encode the unique connection number into "ut_id"
@@ -384,20 +476,6 @@
}
#endif /* defined(HAVE_UT_UT_ID) */
-/*
- * ut_line:
- * size small, e.g. Solaris: 12; FreeBSD: 8
- * pattern conventions differ across systems.
- * So take care in tweaking the template below.
- * Arguably, this could be yet another smb.conf parameter.
- */
-static const char *ut_line_template =
-#if defined(__FreeBSD__)
- "smb%d" ;
-#else
- "smb/%d" ;
-#endif
-
/****************************************************************************
Fill in a utmp (not utmpx) template
****************************************************************************/
@@ -776,20 +854,25 @@
/****************************************************************************
close a connection
****************************************************************************/
-static void utmp_yield(pid_t pid, const connection_struct *conn)
+static BOOL utmp_yield(pid_t pid, const connection_struct *conn)
{
struct utmp u;
int conn_num, i;
if (! lp_utmp(SNUM(conn))) {
DEBUG(2,("utmp_yield: lp_utmp() NULL\n"));
- return;
+ return True;
}
+
+ if (! strcmp(lp_servicename(SNUM(conn)), "IPC$")) {
+ DEBUG(5,("utmp_yield: NO utmp entries for IPC$ service\n"));
+ return True;
+ };
- i = utmp_yield_tdb(conn);
+ i = cnum_fetch_tdb(conn);
if (i < 0) {
- DEBUG(2,("utmp_yield: utmp_yield_tdb() failed\n"));
- return;
+ DEBUG(2,("utmp_yield: cnum_fetch_tdb() failed\n"));
+ return False;
}
conn_num = i;
DEBUG(2,("utmp_yield: conn: user:%s cnum:%d i:%d (utmp_count:%d)\n",
@@ -799,7 +882,7 @@
if (lp_utmp_consolidate()) {
if (utmp_count > 0) {
DEBUG(2,("utmp_yield: utmp consolidate: %d entries still open\n", utmp_count));
- return;
+ return True;
}
else {
/* consolidate; final close: override conn_num */
@@ -821,12 +904,15 @@
if (utmp_fill(&u, conn, pid, conn_num, NULL) == 0) {
utmp_update(&u, NULL, False);
}
+
+ return True;
+
}
/****************************************************************************
open a connection
****************************************************************************/
-static void utmp_claim(const struct connections_data *crec, const connection_struct *conn)
+static BOOL utmp_claim(const struct connections_data *crec, const connection_struct *conn)
{
struct utmp u;
pstring host;
@@ -834,18 +920,23 @@
if (conn == NULL) {
DEBUG(2,("utmp_claim: conn NULL\n"));
- return;
+ return False;
}
if (! lp_utmp(SNUM(conn))) {
DEBUG(2,("utmp_claim: lp_utmp() NULL\n"));
- return;
+ return True;
}
- i = utmp_claim_tdb(conn);
+ if (! strcmp(lp_servicename(SNUM(conn)), "IPC$")) {
+ DEBUG(5,("utmp_claim: NO utmp entries for IPC$ service\n"));
+ return True;
+ }
+
+ i = cnum_fetch_tdb(conn);
if (i < 0) {
- DEBUG(2,("utmp_claim: utmp_claim_tdb() failed\n"));
- return;
+ DEBUG(2,("utmp_claim: cnum_fetch_tdb() failed\n"));
+ return False;
}
pstrcpy(host, lp_utmp_hostname());
@@ -866,7 +957,7 @@
if (lp_utmp_consolidate()) {
if (utmp_count > 1) {
DEBUG(2,("utmp_claim: utmp consolidate: %d entries already open\n", (utmp_count-1)));
- return;
+ return True;
}
else {
/* consolidate; first open: keep record of "i" */
@@ -883,6 +974,44 @@
if (utmp_fill(&u, conn, crec->pid, i, host) == 0) {
utmp_update(&u, host, True);
}
-}
+ return True;
+
+}
#endif /* WITH_UTMP */
+
+#ifdef WITH_PAM
+/*******************************************************************
+ PAM Session handling (same idea as utmp, just with pam)
+
+ Despite what it looks this patch does have a practical purpose:
+ This system allows the administrator to use modules like 'pam_limits'
+ that work on a per session basis. It can be used with ANY pam
+ session module (AFAIK).
+
+ (c) Andrew Bartlett 2001
+********************************************************************/
+
+static BOOL claim_pam(const connection_struct *conn)
+{
+ int cnum;
+ char tty[1024];
+ cnum = cnum_fetch_tdb(conn);
+ slprintf(tty, sizeof(tty), (char *) ut_line_template, cnum);
+ return pam_session(True, conn, tty);
+}
+
+static BOOL yield_pam(const connection_struct *conn)
+{
+ int cnum;
+ char tty[1024];
+ cnum = cnum_fetch_tdb(conn);
+ slprintf(tty, sizeof(tty), (char *) ut_line_template, cnum);
+ return pam_session(False, conn, tty);
+}
+
+#endif /* WITH_PAM */
+
+
+
+
Index: source/smbd/reply.c
===================================================================
RCS file: /cvsroot/samba/source/smbd/reply.c,v
retrieving revision 1.240.2.26
diff -u -r1.240.2.26 reply.c
--- source/smbd/reply.c 2001/04/13 04:09:39 1.240.2.26
+++ source/smbd/reply.c 2001/04/18 00:42:11
Index: source/smbd/server.c
===================================================================
RCS file: /cvsroot/samba/source/smbd/server.c,v
retrieving revision 1.305.2.16
diff -u -r1.305.2.16 server.c
--- source/smbd/server.c 2001/04/09 06:36:14 1.305.2.16
+++ source/smbd/server.c 2001/04/18 00:42:13
@@ -742,7 +742,7 @@
/* Setup the main smbd so that we can get messages. */
if (lp_status(-1)) {
- claim_connection(NULL,"",MAXSTATUS,True);
+ claim_connection(NULL,"");
}
/* Attempt to migrate from an old 2.0.x machine account file. */
Index: source/smbd/service.c
===================================================================
RCS file: /cvsroot/samba/source/smbd/service.c,v
retrieving revision 1.31.2.21
diff -u -r1.31.2.21 service.c
--- source/smbd/service.c 2001/04/13 04:09:39 1.31.2.21
+++ source/smbd/service.c 2001/04/18 00:42:15
@@ -493,9 +493,7 @@
/* check number of connections */
if (!claim_connection(conn,
- lp_servicename(SNUM(conn)),
- lp_max_connections(SNUM(conn)),
- False)) {
+ lp_servicename(SNUM(conn)))) {
DEBUG(1,("too many connections - rejected\n"));
*ecode = ERRnoresource;
conn_free(conn);
More information about the samba-technical
mailing list