]> arthur.barton.de Git - netatalk.git/commitdiff
Initial patch for authenticated printing. Requires LaserWriter 8.5.1 or
authormorgana <morgana>
Fri, 28 Jul 2000 06:27:37 +0000 (06:27 +0000)
committermorgana <morgana>
Fri, 28 Jul 2000 06:27:37 +0000 (06:27 +0000)
greater on client.  See README.MORGAN for information.

20 files changed:
README.MORGAN [new file with mode: 0644]
config/papd.conf
etc/afpd/uam.c
etc/atalkd/zip.c
etc/papd/Makefile
etc/papd/auth.c [new file with mode: 0644]
etc/papd/file.c
etc/papd/file.h
etc/papd/headers.c
etc/papd/lp.c
etc/papd/magics.c
etc/papd/main.c
etc/papd/printer.h
etc/papd/queries.c
etc/papd/session.c
etc/papd/uam.c [new file with mode: 0644]
etc/papd/uam_auth.h [new file with mode: 0644]
etc/uams/uams_guest.c
etc/uams/uams_pam.c
etc/uams/uams_passwd.c

diff --git a/README.MORGAN b/README.MORGAN
new file mode 100644 (file)
index 0000000..d751c6e
--- /dev/null
@@ -0,0 +1,49 @@
+2000/03/04
+
+This readme documents the changes I have made to papd to implement Apple's
+Print Server Security Protocol.  With these patches and appropriate
+configuration choices in papd.conf, a client machine will be required to
+authenticate to papd with a username or userame/password pair before papd
+will spool the print job to lpr.  This requires LaserWriter 8.6.1+ on the
+client Mac.  Papd will switch to the username provided by the client and
+print as that user.
+
+Papd will now respond to the following Postscript queries:
+RBISpoolerID
+RBIUAMListQuery
+RBILogin
+
+Currently, only uams_guest.so, uams_passwd.so, and uams_pam.so
+authentication modules are supported.
+
+To enable authentication on a particular printer, add the "au" flag to
+that printer's entry in papd.conf.  To define which uams to use for
+authentication, use an "am" entry.  The uams defined apply globally, to
+all printers.  It is not currently possible to define different
+authentication methods for different printers.  Here is an example printer
+setup for papd.conf:
+
+lp:\
+       :pr=|/usr/bin/lpr -Plp:\
+       :au:\
+       :am=uams_guest.so,uams_clrtxt.so:\
+       :pd=/usr/local/atalk/etc/ppds/hp8100.ppd:
+
+Or see the example papd.conf.
+
+This patch also includes the patches by Andras Kadinger to enable binary
+printing through papd.
+
+I've only been able to test these changes on a limited number of client
+Macs and only on Linux.  If there are any problems or feedback you'd like
+to give, feel free to send me email.
+
+Hopefully these patches will be incorporated into Adrian Sun's standard
+netatalk distributions, but until then you can find it at:
+
+http://web.orst.edu/~morgan/netatalk/
+
+Enjoy!
+
+Andy Morgan <morgan@orst.edu>
+
index 09f453a06a15fa24f4cccafbbf4a8bf6b46e98ae..c2c89c47858f75b2cacd4d584c8510ecb5bd62e3 100644 (file)
@@ -5,6 +5,10 @@
 #      pr   str  "lp"          LPD printer name.
 #       pa   str  "0.0"         AppleTalk address (not usually needed).
 #      op   str  "operator"    Operator name, for LPD spooling.
+#      au   flag not-present   If present, authentication required
+#      am   str  none          Comma separated list of uams to use
+#                              (for every printer) whenever 
+#                              authentication is on 
 #
 # Some examples:
 #
 #                      :pr=lp:op=wes:\
 #                      :pd=/usr/share/lib/ppd/HPLJ_4M.PPD:
 #
+#      An example with authenticated printing:
+#              authprn:\
+#                      :pr=|/usr/bin/lpr -Plp:\
+#                      :pd=/usr/share/lib/ppd/HPLJ_4M.PPD:\
+#                      :au:\
+#                      :am=uams_clrtxt.so:
+#
 #      Note also that papd.conf can list several printers.
index af39f358f86e29ef3b4a9ab6c2045d01fb595d47..c4e1f138e74fe21fdd35694d648eb6c27d8265db 100644 (file)
@@ -360,3 +360,9 @@ uam_afp_read_err:
   *buflen = 0;
   return len;
 }
+
+/* --- papd-specific functions (just placeholders) --- */
+void append(void *pf, char *data, int len)
+{
+       return;
+}
index 246fcb5900005b07bb893dc7e6d086b9a524a510..9012641ebbc8343d8b21092c05329b423000d440 100644 (file)
@@ -596,13 +596,13 @@ int zip_packet( ap, from, data, len )
            /*
             * Ignore ZIP GNIReplys which are either late or unsolicited.
             */
-           syslog( LOG_INFO, "zip gnireply from %u.%u (%s %x)",
+           syslog( LOG_DEBUG, "zip gnireply from %u.%u (%s %x)",
                    ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
                    iface->i_name, iface->i_flags );
 
            if (( iface->i_flags & ( IFACE_CONFIG|IFACE_PHASE1 )) ||
                    ( iface->i_flags & IFACE_ADDR ) == 0 ) {
-               syslog( LOG_INFO, "zip ignoring gnireply" );
+               syslog( LOG_DEBUG, "zip ignoring gnireply" );
                return 1;
            }
 
index 64148d776d47b71e5010c3c06bfbf9c75322a6f4..9957ddf20315dafde1a834fefa367164ae133924 100644 (file)
@@ -1,13 +1,13 @@
 SRC=    main.c printcap.c session.c file.c comment.c lp.c ppd.c \
-       magics.c headers.c queries.c
+       magics.c headers.c queries.c auth.c uam.c
 OBJ=   main.o printcap.o session.o file.o comment.o lp.o ppd.o \
-       magics.o headers.o queries.o
+       magics.o headers.o queries.o auth.o uam.o
 
 INCPATH = -I../../include ${KRBINCPATH} ${ABSINCPATH}
 CFLAGS=        ${DEFS} ${KRBDEFS} ${ABSDEFS} ${OPTOPTS} ${INCPATH}
 TAGSFILE=      tags
-LIBDIRS=       -L../../libatalk ${KRBLIBDIRS} ${ABSLIBDIRS}
-LIBS=  -latalk ${ABSLIBS} ${KRBLIBS} ${ADDLIBS}
+LIBDIRS=       -L../../libatalk ${KRBLIBDIRS} ${ABSLIBDIRS} ${PAMLIBDIRS}
+LIBS=  -latalk ${ABSLIBS} ${KRBLIBS} ${ADDLIBS} ${PAMLIBS} ${LIBSHARED}
 CC=    cc
 INSTALL=       install
 
@@ -18,10 +18,20 @@ all :
            KRBINCPATH="-I${KRBDIR}/include"; \
            KRBDEFS="-DKRB"; \
        fi; \
+       if [ x"${PAMDIR}" != x ]; then \
+           PAMLIBS="-lpam"; \
+           if [ "${PAMDIR}" != "/usr" ]; then \
+             PAMLIBDIRS="-L${PAMDIR}/lib"; \
+             PAMINCPATH="-I${PAMDIR}/include"; \
+           fi; \
+           PAMDEFS="-DUSE_PAM"; \
+       fi; \
         ${MAKE} ${MFLAGS} CC="${CC}" ADDLIBS="${ADDLIBS}" DEFS="${DEFS}" \
            OPTOPTS="${OPTOPTS}" DESTDIR="${DESTDIR}" \
            SBINDIR="${SBINDIR}" BINDIR="${BINDIR}" RESDIR="${RESDIR}" \
            ETCDIR="${ETCDIR}" LIBDIR="${LIBDIR}" INCDIR="${INCDIR}" \
+           PAMLIBS="$${PAMLIBS}" PAMLIBDIRS="$${PAMLIBDIRS}" \
+           PAMINCPATH="$${PAMINCPATH}" PAMDEFS="$${PAMDEFS}" \
            KRBLIBS="$${KRBLIBS}" KRBLIBDIRS="$${KRBLIBDIRS}" \
            KRBINCPATH="$${KRBINCPATH}" KRBDEFS="$${KRBDEFS}" papd showppd
 
@@ -51,13 +61,18 @@ showppd: showppd.c ppd.c
        ${CC} ${CFLAGS} -DSHOWPPD -o showppd showppd.c ppd.c
 
 papd : ${OBJ} ../../libatalk/libatalk.a
-       ${CC} ${CFLAGS} ${LDFLAGS} -o papd ${OBJ} ${LIBDIRS} ${LIBS}
+       ${CC} ${CFLAGS} ${LDFLAGS_EXPORT} ${PAMINCPATH} ${PAMDEFS} \
+               ${LDFLAGS} -o papd ${OBJ} ${LIBDIRS} ${LIBS}
 
 main.o : main.c
        ${CC} ${CFLAGS} -D_PATH_PAPDCONF=\"${ETCDIR}/papd.conf\" \
+           -D_PATH_PAPDUAMPATH=\"${RESDIR}/uams/\" \
            -DVERSION=\"`cat ../../VERSION`\" \
            ${CPPFLAGS} -c main.c
 
+queries.o : queries.c
+       ${CC} ${CFLAGS} ${PAMDEFS} -c queries.c
+
 install : all
        ${INSTALL} -c papd ${SBINDIR}
        ${INSTALL} -c showppd ${BINDIR}
diff --git a/etc/papd/auth.c b/etc/papd/auth.c
new file mode 100644 (file)
index 0000000..90f4161
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1990,1993 Regents of The University of Michigan.
+ * All Rights Reserved.  See COPYRIGHT.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <netatalk/endian.h>
+#include <atalk/afp.h>
+#include <atalk/compat.h>
+#include <atalk/util.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+#include <syslog.h>
+
+#include "uam_auth.h"
+
+static struct uam_mod uam_modules = {NULL, NULL, &uam_modules, &uam_modules};
+static struct uam_obj uam_login = {"", "", 0, {{NULL}}, &uam_login,
+                                  &uam_login};
+static struct uam_obj uam_changepw = {"", "", 0, {{NULL}}, &uam_changepw, 
+                                     &uam_changepw};
+static struct uam_obj uam_printer = {"", "", 0, {{NULL}}, &uam_printer,
+                                       &uam_printer};
+
+
+/*
+ * Return a list of names for loaded uams
+ */
+int getuamnames(const int type, char *uamnames)
+{
+    struct uam_obj *prev, *start;
+  
+    if (!(start = UAM_LIST(type)))
+        return(-1);
+  
+    prev = start;
+      
+    while((prev = prev->uam_prev) != start) {
+        strcat(uamnames, prev->uam_name);
+        strcat(uamnames, "\n");
+    }
+    strcat(uamnames, "*\n");
+    return(0);
+}
+  
+
+/* just do a linked list search. this could be sped up with a hashed
+ * list, but i doubt anyone's going to have enough uams to matter. */
+struct uam_obj *auth_uamfind(const int type, const char *name, 
+                            const int len)
+{
+  struct uam_obj *prev, *start;
+
+  if (!name || !(start = UAM_LIST(type)))
+    return NULL;
+
+  prev = start;
+  while ((prev = prev->uam_prev) != start) 
+    if (strndiacasecmp(prev->uam_name, name, len) == 0)
+      return prev;
+
+  return NULL;
+}
+
+int auth_register(const int type, struct uam_obj *uam)
+{
+  struct uam_obj *start;
+
+  if (!uam || !uam->uam_name || (*uam->uam_name == '\0'))
+    return -1;
+
+  if (!(start = UAM_LIST(type)))
+    return 0; /* silently fail */
+
+  uam_attach(start, uam);
+  return 0;
+}
+
+/* load all of the modules */
+int auth_load(const char *path, const char *list)
+{
+  char name[MAXPATHLEN + 1], buf[MAXPATHLEN + 1], *p; 
+  struct uam_mod *mod;
+  struct stat st;
+  int len;
+  
+  if (!path || !list || (len = strlen(path)) > sizeof(name) - 2)
+    return -1;
+
+  strncpy(buf, list, sizeof(buf));
+  if ((p = strtok(buf, ",")) == NULL)
+    return -1;
+
+  strcpy(name, path);
+  if (name[len - 1] != '/') {
+    strcat(name, "/");
+    len++;
+  }
+
+  while (p) {
+    strncpy(name + len, p, sizeof(name) - len);
+    if ((stat(name, &st) == 0) && (mod = uam_load(name, p))) {
+      uam_attach(&uam_modules, mod);
+      syslog(LOG_INFO, "uam: %s loaded", p);
+    }
+    p = strtok(NULL, ",");
+  }
+}
+
+/* get rid of all of the uams */
+void auth_unload()
+{
+  struct uam_mod *mod, *prev, *start = &uam_modules;
+
+  prev = start->uam_prev;
+  while ((mod = prev) != start) {
+    prev = prev->uam_prev;
+    uam_detach(mod);
+    uam_unload(mod);
+  }
+}
index 63f08a06c6738304920dcf825d4af2de4c8cd921..5616d3e8b3a29b04926e39ed64e01f9146a200a7 100644 (file)
 
 #include "file.h"
 
-markline( start, stop, pf )
-    char               **start, **stop;
+markline( pf, start, linelength, crlflength )
+    char               **start;
+    int                        *linelength, *crlflength;
     struct papfile     *pf;
 {
     char               *p;
 
-    if ( PF_BUFSIZ( pf ) == 0 && ( pf->pf_state & PF_EOF )) {
+    if ( pf->pf_datalen == 0 && ( pf->pf_state & PF_EOF )) {
        return( 0 );
     }
 
+    *start = pf->pf_data;
+
     /* get a line */
-    for ( p = pf->pf_cur; p < pf->pf_end; p++ ) {
-       if ( *p == '\n' || *p == '\r' ) {
+    for ( *linelength=0; *linelength < pf->pf_datalen; (*linelength)++) {
+       if (pf->pf_data[*linelength] == '\n' ||
+           pf->pf_data[*linelength] == '\r') {
            break;
        }
     }
-    if ( p >= pf->pf_end ) {
+
+    if ( *linelength >= pf->pf_datalen ) {
        if ( pf->pf_state & PF_EOF ) {
-           APPEND( pf, "\n", 1 );
-       } else {
+           append( pf, "\n", 1 );
+       } else if (*linelength < 1024) {
            return( -1 );
        }
     }
 
-    *start = pf->pf_cur;
-    *stop = p;
-    if ( *stop == *start ) {
-       return( 1 );                    /* don't return len 0 lines */
-    } else {
-       return( *stop - *start );
-    }
-}
+    p = pf->pf_data + *linelength;
 
-consumetomark( start, stop, pf )
-    char               *start, *stop;
-    struct papfile     *pf;
-{
-    if ( start != pf->pf_cur || pf->pf_cur > stop || stop > pf->pf_end ) {
-       abort();
-    }
-
-    pf->pf_cur = stop + 1;             /* past the stop char */
-    if ( pf->pf_cur > pf->pf_end ) {
-       abort();
-    }
-    if ( pf->pf_cur == pf->pf_end ) {
-       pf->pf_cur = pf->pf_end = pf->pf_buf;
+    *crlflength=0;
+    while(*crlflength < pf->pf_datalen-*linelength && 
+    (p[*crlflength]=='\r' || p[*crlflength]=='\n')) {
+       (*crlflength)++;
     }
 
-    return;
+    return *linelength;
 }
 
 morespace( pf, data, len )
@@ -71,15 +59,14 @@ morespace( pf, data, len )
     char               *nbuf;
     int                        nsize;
 
-    if ( pf->pf_cur != pf->pf_buf ) {                  /* pull up */
-       bcopy( pf->pf_cur, pf->pf_buf, PF_BUFSIZ( pf ));
-       pf->pf_end = pf->pf_buf + PF_BUFSIZ( pf );
-       pf->pf_cur = pf->pf_buf;
+    if ( pf->pf_data != pf->pf_buf ) {                 /* pull up */
+       bcopy( pf->pf_data, pf->pf_buf, pf->pf_datalen);
+       pf->pf_data = pf->pf_buf;
     }
 
-    if ( pf->pf_end + len > pf->pf_buf + pf->pf_len ) {        /* make more space */
-       nsize = (( pf->pf_len + len ) / PF_MORESPACE +
-               (( pf->pf_len + len ) % PF_MORESPACE != 0 )) * PF_MORESPACE;
+    if ( pf->pf_datalen + len > pf->pf_bufsize ) {     /* make more space */
+       nsize = (( pf->pf_bufsize + len ) / PF_MORESPACE +
+               (( pf->pf_bufsize + len ) % PF_MORESPACE != 0 )) * PF_MORESPACE;
        if ( pf->pf_buf ) {
            if (( nbuf = (char *)realloc( pf->pf_buf, nsize )) == 0 ) {
                exit( 1 );
@@ -89,16 +76,31 @@ morespace( pf, data, len )
                exit( 1 );
            }
        }
-       pf->pf_len = nsize;
-       pf->pf_end = nbuf + ( pf->pf_end - pf->pf_buf );
-       pf->pf_cur = nbuf + ( pf->pf_cur - pf->pf_buf );
+       pf->pf_bufsize = nsize;
+       pf->pf_data = nbuf + ( pf->pf_data - pf->pf_buf );
        pf->pf_buf = nbuf;
     }
 
-    bcopy( data, pf->pf_end, len );
-    pf->pf_end += len;
+    bcopy( data, pf->pf_data + pf->pf_datalen, len );
+    pf->pf_datalen += len;
 }
 
+
+append(pf, data, len)
+    struct papfile     *pf;
+    char               *data;
+    int                        len;
+{
+    if ((pf->pf_data + pf->pf_datalen + len) >
+       (pf->pf_buf + pf->pf_bufsize)) {
+               morespace(pf, data, len);
+    } else {
+       bcopy(data, pf->pf_data + pf->pf_datalen, len);
+       pf->pf_datalen += len;
+    }
+}
+
+
 spoolerror( out, str )
     struct papfile     *out;
     char               *str;
@@ -110,7 +112,7 @@ spoolerror( out, str )
        str = "Spooler error.";
     }
 
-    APPEND( out, pserr1, strlen( pserr1 ));
-    APPEND( out, str, strlen( str ));
-    APPEND( out, pserr2, strlen( pserr2 ));
+    append( out, pserr1, strlen( pserr1 ));
+    append( out, str, strlen( str ));
+    append( out, pserr2, strlen( pserr2 ));
 }
index e6ae71e0676a616a63a526c3367998c1c1ef5897..f33800d2495b319628d167ddf873db2d118e1842 100644 (file)
@@ -6,26 +6,22 @@
 struct papfile {
     int                        pf_state;
     struct state       *pf_xstate;
-    int                        pf_len;
+    int                        pf_bufsize;
+    int                        pf_datalen;
     char               *pf_buf;
-    char               *pf_cur;
-    char               *pf_end;
+    char               *pf_data;
 };
 
 #define PF_BOT         (1<<0)
 #define PF_EOF         (1<<1)
 #define PF_QUERY       (1<<2)
 
-#define APPEND( pf, data, len )        \
-       if ( (pf)->pf_end + (len) > (pf)->pf_buf + (pf)->pf_len ) { \
-               morespace( (pf), (data), (len)); \
-       } else { \
-               bcopy( (data), (pf)->pf_end, (len)); \
-               (pf)->pf_end += (len); \
-       }
-#define PF_BUFSIZ( pf )                ((pf)->pf_end - (pf)->pf_cur)
-#define CONSUME( pf, len )     (((pf)->pf_cur += (len)), \
-       (((pf)->pf_cur >= (pf)->pf_end) && \
-       ((pf)->pf_cur = (pf)->pf_end = (pf)->pf_buf)))
+#define CONSUME( pf, len )  {   (pf)->pf_data += (len); \
+                               (pf)->pf_datalen -= (len); \
+                               if ((pf)->pf_datalen <= 0) { \
+                                   (pf)->pf_data = (pf)->pf_buf; \
+                                   (pf)->pf_datalen = 0; \
+                               } \
+                           }
 
 #define PF_MORESPACE   1024
index 12104bea1857e80b945a15b77a9a15a3c9cc12e4..0b5dfc36150357026765ab8d0b36a1feee78be3e 100644 (file)
@@ -14,9 +14,10 @@ ch_title( in, out )
     struct papfile     *in, *out;
 {
     char               *start, *stop, *p, *q, c;
+    int                        linelength, crlflength;
     struct comment     *comment = compeek();
 
-    switch ( markline( &start, &stop, in )) {
+    switch ( markline( in, &start, &linelength, &crlflength )) {
     case 0 :
        return( 0 );
 
@@ -24,6 +25,7 @@ ch_title( in, out )
        return( CH_MORE );
     }
 
+    stop = start + linelength;
     for ( p = start; p < stop; p++ ) {
        if ( *p == ':' ) {
            break;
@@ -50,10 +52,9 @@ ch_title( in, out )
        *q = c;
     }
 
-    *stop = '\n';
-    lp_write( start, stop - start + 1 );
+    lp_write( start, linelength + crlflength );
     compop();
-    consumetomark( start, stop, in );
+    CONSUME( in, linelength + crlflength );
     return( CH_DONE );
 }
 
index be1e6c7171d1fb7ba32527d7ddfa8635f9c57508..60ae548c8aedf73680f6dc4da6bab0ddeaddf796 100644 (file)
@@ -573,6 +573,7 @@ lp_queue( out )
     struct papfile     *out;
 {
     char                       buf[ 1024 ], *start, *stop, *p, *q;
+    int                                linelength, crlflength;
     static struct papfile      pf;
     int                                n, len, s;
        
@@ -591,19 +592,20 @@ lp_queue( out )
     pf.pf_state = PF_BOT;
 
     while (( n = read( s, buf, sizeof( buf ))) > 0 ) {
-       APPEND( &pf, buf, n );
+       append( &pf, buf, n );
     }
 
     for (;;) {
-       if ( markline( &start, &stop, &pf ) > 0 ) {
+       if ( markline( &pf, &start, &linelength, &crlflength ) > 0 ) {
            /* parse */
+           stop = start + linelength;
            for ( p = start; p < stop; p++ ) {
                if ( *p == ' ' || *p == '\t' ) {
                    break;
                }
            }
            if ( p >= stop ) {
-               consumetomark( start, stop, &pf );
+               CONSUME( &pf , linelength + crlflength);
                continue;
            }
 
@@ -614,15 +616,15 @@ lp_queue( out )
            len = p - start;
            if ( len == strlen( kw_rank ) &&
                    strncmp( kw_rank, start, len ) == 0 ) {
-               consumetomark( start, stop, &pf );
+               CONSUME( &pf, linelength + crlflength );
                continue;
            }
            if (( len == strlen( kw_active ) &&
                    strncmp( kw_active, start, len ) == 0 ) ||
                    isdigit( *start )) {                /* a job line */
-               APPEND( out, tag_rank, strlen( tag_rank ));
-               APPEND( out, start, p - start );
-               APPEND( out, "\n", 1 );
+               append( out, tag_rank, strlen( tag_rank ));
+               append( out, start, p - start );
+               append( out, "\n", 1 );
 
                for ( ; p < stop; p++ ) {
                    if ( *p != ' ' && *p != '\t' ) {
@@ -635,13 +637,13 @@ lp_queue( out )
                    }
                }
                if ( p >= stop ) {
-                   APPEND( out, ".\n", 2 );
-                   consumetomark( start, stop, &pf );
+                   append( out, ".\n", 2 );
+                   CONSUME( &pf, linelength + crlflength );
                    continue;
                }
-               APPEND( out, tag_owner, strlen( tag_owner ));
-               APPEND( out, q, p - q );
-               APPEND( out, "\n", 1 );
+               append( out, tag_owner, strlen( tag_owner ));
+               append( out, q, p - q );
+               append( out, "\n", 1 );
 
                for ( ; p < stop; p++ ) {
                    if ( *p != ' ' && *p != '\t' ) {
@@ -654,13 +656,13 @@ lp_queue( out )
                    }
                }
                if ( p >= stop ) {
-                   APPEND( out, ".\n", 2 );
-                   consumetomark( start, stop, &pf );
+                   append( out, ".\n", 2 );
+                   CONSUME( &pf , linelength + crlflength );
                    continue;
                }
-               APPEND( out, tag_job, strlen( tag_job ));
-               APPEND( out, q, p - q );
-               APPEND( out, "\n", 1 );
+               append( out, tag_job, strlen( tag_job ));
+               append( out, q, p - q );
+               append( out, "\n", 1 );
 
                for ( ; p < stop; p++ ) {
                    if ( *p != ' ' && *p != '\t' ) {
@@ -683,35 +685,35 @@ lp_queue( out )
                    }
                }
                if ( p <= q ) {
-                   APPEND( out, ".\n", 2 );
-                   consumetomark( start, stop, &pf );
+                   append( out, ".\n", 2 );
+                   CONSUME( &pf, linelength + crlflength );
                    continue;
                }
-               APPEND( out, tag_files, strlen( tag_files ));
-               APPEND( out, q, p - q );
-               APPEND( out, "\n", 1 );
+               append( out, tag_files, strlen( tag_files ));
+               append( out, q, p - q );
+               append( out, "\n", 1 );
 
                for ( ; p < stop; p++ ) {
                    if ( *p != ' ' && *p != '\t' ) {
                        break;
                    }
                }
-               APPEND( out, tag_size, strlen( tag_size ));
-               APPEND( out, p, stop - p );
-               APPEND( out, "\n.\n", 3 );
+               append( out, tag_size, strlen( tag_size ));
+               append( out, p, stop - p );
+               append( out, "\n.\n", 3 );
 
-               consumetomark( start, stop, &pf );
+               CONSUME( &pf, linelength + crlflength );
                continue;
            }
 
            /* status */
-           APPEND( out, tag_status, strlen( tag_status ));
-           APPEND( out, start, stop - start );
-           APPEND( out, "\n.\n", 3 );
+           append( out, tag_status, strlen( tag_status ));
+           append( out, start, linelength );
+           append( out, "\n.\n", 3 );
 
-           consumetomark( start, stop, &pf );
+           CONSUME( &pf, linelength + crlflength );
        } else {
-           APPEND( out, "*\n", 2 );
+           append( out, "*\n", 2 );
            lp_disconn_unix( s );
            return( 0 );
        }
index dea2c009ab0f8db842e8fd796107bcc4e397fa49..b6d1ffe0e45bb037460c4f1cc9a77d30e3c7ab6c 100644 (file)
@@ -14,7 +14,8 @@
 ps( infile, outfile )
     struct papfile     *infile, *outfile;
 {
-    char                       *start, *stop;
+    char                       *start;
+    int                                linelength, crlflength;
     struct comment             *comment;
 
     for (;;) {
@@ -31,7 +32,7 @@ ps( infile, outfile )
            }
 
        } else {
-           switch ( markline( &start, &stop, infile )) {
+           switch ( markline( infile, &start, &linelength, &crlflength )) {
            case 0 :
                /* eof on infile */
                outfile->pf_state |= PF_EOF;
@@ -43,7 +44,7 @@ ps( infile, outfile )
            }
 
            if ( infile->pf_state & PF_BOT ) {
-               if (( comment = commatch( start, stop, magics )) != NULL ) {
+               if (( comment = commatch( start, start+linelength, magics )) != NULL ) {
                    compush( comment );
                    continue;   /* top of for (;;) */
                }
@@ -57,9 +58,8 @@ ps( infile, outfile )
            }
 
            /* write to file */
-           *stop = '\n';
-           lp_write( start, stop - start + 1 );
-           consumetomark( start, stop, infile );
+           lp_write( start, linelength + crlflength );
+           CONSUME( infile, linelength + crlflength );
        }
     }
 }
@@ -68,10 +68,11 @@ cm_psquery( in, out )
     struct papfile     *in, *out;
 {
     struct comment     *comment;
-    char               *start, *stop;
+    char               *start;
+    int                        linelength, crlflength;
 
     for (;;) {
-       switch ( markline( &start, &stop, in )) {
+       switch ( markline( in, &start, &linelength, &crlflength )) {
        case 0 :
            /* eof on infile */
            out->pf_state |= PF_EOF;
@@ -85,24 +86,25 @@ cm_psquery( in, out )
        if ( in->pf_state & PF_BOT ) {
            in->pf_state &= ~PF_BOT;
        } else {
-           if (( comment = commatch( start, stop, queries )) != NULL ) {
+           if (( comment = commatch( start, start+linelength, queries )) != NULL ) {
                compush( comment );
                return( CH_DONE );
            }
        }
 
-       consumetomark( start, stop, in );
+       CONSUME( in, linelength + crlflength );
     }
 }
 
 cm_psadobe( in, out )
     struct papfile     *in, *out;
 {
-    char               *start, *stop;
+    char               *start;
+    int                        linelength, crlflength;
     struct comment     *comment = compeek();
 
     for (;;) {
-       switch ( markline( &start, &stop, in )) {
+       switch ( markline( in, &start, &linelength, &crlflength )) {
        case 0 :
            /* eof on infile */
            out->pf_state |= PF_EOF;
@@ -120,15 +122,14 @@ cm_psadobe( in, out )
                spoolerror( out, "Ignoring job." );
            }
        } else {
-           if (( comment = commatch( start, stop, headers )) != NULL ) {
+           if (( comment = commatch( start, start + linelength, headers )) != NULL ) {
                compush( comment );
                return( CH_DONE );
            }
        }
 
-       *stop = '\n';
-       lp_write( start, stop - start + 1 );
-       consumetomark( start, stop, in );
+       lp_write( start, linelength + crlflength );
+       CONSUME( in, linelength + crlflength );
     }
 }
 
@@ -138,9 +139,10 @@ cm_psswitch( in, out )
     struct papfile     *in, *out;
 {
     char               *start, *stop, *p;
+    int                        linelength, crlflength;
     struct comment     *comment = compeek();
 
-    switch ( markline( &start, &stop, in )) {
+    switch ( markline( in, &start, &linelength, &crlflength )) {
     case 0 :
        /* eof on infile */
        out->pf_state |= PF_EOF;
@@ -151,6 +153,7 @@ cm_psswitch( in, out )
        return( CH_MORE );
     }
 
+    stop = start + linelength;
     for ( p = start; p < stop; p++ ) {
        if ( *p == ' ' || *p == '\t' ) {
            break;
index 4b2239b390e3a03cf7c6292aaa9db9fae17a3b14..d9dc1aa11d4ddf79bee97b492ab5397cdfa9051b 100644 (file)
@@ -51,10 +51,14 @@ struct printer      *printer = NULL;
 char           *version = VERSION;
 static char      *pidfile = _PATH_PAPDLOCK;
 
+char           *uamlist;
+char           *uampath = _PATH_PAPDUAMPATH;
+
 /* this only needs to be used by the server process */
 static void papd_exit(const int i)
 {
   server_unlock(pidfile);
+  auth_unload();
   exit(i);
 }
 
@@ -236,6 +240,12 @@ main( ac, av )
                    pr->p_zone );
            die( 1 );
        }
+       if ( pr->p_flags & P_AUTH ) {
+               syslog( LOG_INFO, "Authentication enabled: %s", pr->p_name );
+       }
+       else {
+               syslog( LOG_INFO, "Authentication disabled: %s", pr->p_name );
+       }
        syslog( LOG_INFO, "register %s:%s@%s", pr->p_name, pr->p_type,
                pr->p_zone );
        pr->p_flags |= P_REGISTERED;
@@ -258,6 +268,11 @@ main( ac, av )
        papd_exit( 1 );
     }
 
+    /*
+     * Load UAMS
+     */
+    auth_load(uampath, uamlist);
+
     /*
      * Begin accepting connections.
      */
@@ -570,6 +585,23 @@ getprinters( cf )
            strcpy( pr->p_printer, p );
        }
 
+       /*
+        * Do we want authenticated printing?
+        */
+       if ( pgetflag( "au", &a ) == 1 ) {
+           pr->p_flags |= P_AUTH;
+       } else {
+           pr->p_flags &= ~P_AUTH;
+       }
+
+       if ((p = pgetstr("am", &a)) != NULL ) {
+               if ((uamlist = (char *)malloc(strlen(p)+1)) == NULL ) {
+                       perror("malloc");
+                       exit(1);
+               }
+               strcpy(uamlist, p);
+       }
+
        if ( pr->p_flags & P_SPOOLED ) {
            /*
             * Get operator name.
@@ -714,9 +746,9 @@ rprintcap( pr )
         * Must Kerberos authenticate?
         */
        if ( pgetflag( "ka" ) == 1 ) {
-           pr->p_flags |= P_AUTH;
+           pr->p_flags |= P_KRB;
        } else {
-           pr->p_flags &= ~P_AUTH;
+           pr->p_flags &= ~P_KRB;
        }
 #endif
 
index 72ce5b6c919454613ef20965e4a3bb9f921ac789..f60e6612ad03676c7395daf69184f72576f5aaff 100644 (file)
@@ -50,6 +50,7 @@ struct printer {
 #define P_SPOOLED      (1<<1)
 #define P_REGISTERED   (1<<2)
 #define P_ACCOUNT      (1<<3)
-#define P_AUTH         (1<<4)
+#define P_KRB          (1<<4)
+#define P_AUTH         (1<<5)
 
 extern struct printer  *printer;
index 28df08003b65f6c3b4d02cc10bffcbb8a88b8e14..2d83b08549bb1b0d178479f49f1dd2d2cdf45dc3 100644 (file)
 #include "comment.h"
 #include "printer.h"
 #include "ppd.h"
+#include "uam_auth.h"
 
 cq_default( in, out )
     struct papfile     *in, *out;
 {
     char               *start, *stop, *p;
+    int                        linelength, crlflength;
     struct comment     *comment = compeek();
 
     for (;;) {
-       switch ( markline( &start, &stop, in )) {
+       switch ( markline( in, &start, &linelength, &crlflength )) {
        case 0 :
            return( 0 );
 
@@ -39,17 +41,19 @@ cq_default( in, out )
            return( CH_MORE );
        }
 
+       stop = start+linelength;
+
        if ( comgetflags() == 0 ) {     /* started */
            if ( comment->c_end ) {
                comsetflags( 1 );
            } else {
                compop();
-               consumetomark( start, stop, in );
+               CONSUME( in, linelength + crlflength );
                return( CH_DONE );
            }
        } else {
            /* return default */
-           if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
+           if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) {
                for ( p = start; p < stop; p++ ) {
                    if ( *p == ':' ) {
                        break;
@@ -60,15 +64,14 @@ cq_default( in, out )
                    p++;
                }
 
-               *stop = '\n';
-               APPEND( out, p, stop - p + 1 );
+               append( out, p, stop - p + crlflength );
                compop();
-               consumetomark( start, stop, in );
+               CONSUME( in, linelength + crlflength );
                return( CH_DONE );
            }
        }
 
-       consumetomark( start, stop, in );
+       CONSUME( in, linelength + crlflength );
     }
 }
 
@@ -81,14 +84,15 @@ char        *LoginFailed = "LoginFailed\n";
 cq_k4login( in, out )
     struct papfile     *in, *out;
 {
-    char               *start, *stop, *p;
+    char               *start, *p;
+    int                        linelength, crlflength;
     unsigned char      *t;
     struct comment     *comment = compeek();
     KTEXT_ST           tkt;
     AUTH_DAT           ad;
     int                        rc, i;
 
-    switch ( markline( &start, &stop, in )) {
+    switch ( markline( in, &start, &linelength, &crlflength )) {
     case 0 :
        return( 0 );
 
@@ -102,6 +106,7 @@ cq_k4login( in, out )
     }
 
     bzero( &tkt, sizeof( tkt ));
+    stop = start+linelength;
     for ( i = 0, t = tkt.dat; p < stop; p += 2, t++, i++ ) {
        *t = ( h2b( (unsigned char)*p ) << 4 ) +
                h2b( (unsigned char)*( p + 1 ));
@@ -111,9 +116,9 @@ cq_k4login( in, out )
     if (( rc = krb_rd_req( &tkt, "LaserWriter", printer->p_name,
            0, &ad, "" )) != RD_AP_OK ) {
        syslog( LOG_ERR, "cq_k4login: %s", krb_err_txt[ rc ] );
-       APPEND( out, LoginFailed, strlen( LoginFailed ));
+       append( out, LoginFailed, strlen( LoginFailed ));
        compop();
-       consumetomark( start, stop, in );
+       CONSUME( in, linelength + crlflength );
        return( CH_DONE );
     }
     syslog( LOG_INFO, "cq_k4login: %s.%s@%s", ad.pname, ad.pinst,
@@ -121,9 +126,9 @@ cq_k4login( in, out )
     lp_person( ad.pname );
     lp_host( ad.prealm );
 
-    APPEND( out, LoginOK, strlen( LoginOK ));
+    append( out, LoginOK, strlen( LoginOK ));
     compop();
-    consumetomark( start, stop, in );
+    CONSUME( in, linelength + crlflength);
     return( CH_DONE );
 }
 
@@ -132,11 +137,12 @@ char      *uameth = "UMICHKerberosIV\n*\n";
 cq_uameth( in, out )
     struct papfile     *in, *out;
 {
-    char               *start, *stop;
+    char               *start;
+    int                        linelength, crlflength;
     struct comment     *c, *comment = compeek();
 
     for (;;) {
-       switch ( markline( &start, &stop, in )) {
+       switch ( markline( in, &start, &linelength, &crlflength )) {
        case 0 :
            return( 0 );
 
@@ -145,7 +151,7 @@ cq_uameth( in, out )
        }
 
        if ( comgetflags() == 0 ) {     /* start */
-           if (( printer->p_flags & P_AUTH ) == 0 ) {  /* no kerberos */
+           if (( printer->p_flags & P_KRB ) == 0 ) {   /* no kerberos */
                if ( comswitch( queries, cq_default ) < 0 ) {
                    syslog( LOG_ERR, "cq_uameth: can't find default!" );
                    exit( 1 );
@@ -155,13 +161,13 @@ cq_uameth( in, out )
            comsetflags( 1 );
        } else {
            if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) { /* end */
-               APPEND( out, uameth, strlen( uameth ));
+               append( out, uameth, strlen( uameth ));
                compop();
                return( CH_DONE );
            }
        }
 
-       consumetomark( start, stop, in );
+       CONSUME( in, linelength + crlflength );
     }
 }
 #endif KRB
@@ -170,7 +176,7 @@ gq_true( out )
     struct papfile     *out;
 {
     if ( printer->p_flags & P_SPOOLED ) {
-       APPEND( out, "true\n", 5 );
+       append( out, "true\n", 5 );
        return( 0 );
     } else {
        return( -1 );
@@ -184,18 +190,18 @@ gq_pagecost( out )
 
     /* check for spooler? XXX */
     if ( printer->p_pagecost_msg != NULL ) {
-       APPEND( out, printer->p_pagecost_msg,
+       append( out, printer->p_pagecost_msg,
                strlen( printer->p_pagecost_msg ));
     } else if ( printer->p_flags & P_ACCOUNT ) {
 #ifdef ABS_PRINT
        lp_pagecost();
 #endif ABS_PRINT
        sprintf( cost, "%d", printer->p_pagecost );
-       APPEND( out, cost, strlen( cost ));
+       append( out, cost, strlen( cost ));
     } else {
        return( -1 );
     }
-    APPEND( out, "\n", 1 );
+    append( out, "\n", 1 );
     return( 0 );
 }
 
@@ -209,11 +215,53 @@ gq_balance( out )
        return( -1 );
     }
     sprintf( balance, "$%1.2f\n", printer->p_balance );
-    APPEND( out, balance, strlen( balance ));
+    append( out, balance, strlen( balance ));
     return( 0 );
 }
 #endif ABS_PRINT
 
+
+/*
+ * Handler for RBISpoolerID
+ */
+
+static const char *spoolerid = "(PAPD Spooler) 2.1 (2.1.4 pre-release)\n";
+
+gq_rbispoolerid( out )
+    struct papfile     *out;
+{
+    append( out, spoolerid, strlen( spoolerid ));
+    return(0);
+}
+
+
+
+/*
+ * Handler for RBIUAMListQuery
+ */
+
+static const char *nouams = "*\n";
+
+gq_rbiuamlist( out )
+    struct papfile      *out;
+{
+    char uamnames[128] = "\0";
+
+    if (printer->p_flags & P_AUTH) {
+       if (getuamnames(UAM_SERVER_PRINTAUTH, uamnames) < 0) {
+           append(out, nouams, strlen(nouams));
+           return(0);
+       } else {
+           append(out, uamnames, strlen(uamnames));
+           return(0);
+       }
+    } else {
+       append(out, nouams, strlen(nouams));
+       return(0);
+    }
+}
+
+
 struct genquery {
     char       *gq_name;
     int                (*gq_handler)();
@@ -222,6 +270,8 @@ struct genquery {
 #ifdef notdef
     { "UMICHUserBalance", gq_balance },
 #endif 
+    { "RBISpoolerID",  gq_rbispoolerid },
+    { "RBIUAMListQuery", gq_rbiuamlist },
     { "UMICHListQueue", gq_true },
     { "UMICHDeleteJob", gq_true },
     { NULL },
@@ -231,12 +281,13 @@ cq_query( in, out )
     struct papfile     *in, *out;
 {
     char               *start, *stop, *p, *q;
+    int                        linelength, crlflength;
     struct comment     *comment = compeek();
     struct genquery    *gq;
 
 
     for (;;) {
-       switch ( markline( &start, &stop, in )) {
+       switch ( markline( in, &start, &linelength, &crlflength )) {
        case 0 :
            return( 0 );
 
@@ -244,6 +295,8 @@ cq_query( in, out )
            return( CH_MORE );
        }
 
+       stop = start+linelength;
+
        if ( comgetflags() == 0 ) {     /* started */
            comsetflags( 1 );
 
@@ -282,12 +335,12 @@ cq_query( in, out )
        } else {
            if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
                compop();
-               consumetomark( start, stop, in );
+               CONSUME( in, linelength + crlflength );
                return( CH_DONE );
            }
        }
 
-       consumetomark( start, stop, in );
+       CONSUME( in, linelength + crlflength );
     }
 }
 
@@ -313,14 +366,14 @@ cq_font_answer( start, stop, out )
        if ( q != buf ) {
            *q = '\0';
 
-           APPEND( out, "/", 1 );
-           APPEND( out, buf, strlen( buf ));
-           APPEND( out, ":", 1 );
+           append( out, "/", 1 );
+           append( out, buf, strlen( buf ));
+           append( out, ":", 1 );
 
            if (( pfo = ppd_font( buf )) == NULL ) {
-               APPEND( out, "No\n", 3 );
+               append( out, "No\n", 3 );
            } else {
-               APPEND( out, "Yes\n", 4 );
+               append( out, "Yes\n", 4 );
            }
        }
     }
@@ -332,10 +385,11 @@ cq_font( in, out )
     struct papfile     *in, *out;
 {
     char               *start, *stop, *p;
+    int                        linelength, crlflength;
     struct comment     *comment = compeek();
 
     for (;;) {
-       switch ( markline( &start, &stop, in )) {
+       switch ( markline( in, &start, &linelength, &crlflength )) {
        case 0 :
            return( 0 );
 
@@ -343,6 +397,8 @@ cq_font( in, out )
            return( CH_MORE );
        }
 
+       stop = start + linelength;
+
        if ( comgetflags() == 0 ) {
            comsetflags( 1 );
 
@@ -370,15 +426,15 @@ cq_font( in, out )
            } else {
                comsetflags( 2 );
                if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
-                   APPEND( out, "*\n", 2 );
+                   append( out, "*\n", 2 );
                    compop();
-                   consumetomark( start, stop, in );
+                   CONSUME( in, linelength + crlflength );
                    return( CH_DONE );
                }
            }
        }
 
-       consumetomark( start, stop, in );
+        CONSUME( in, linelength + crlflength );
     }
 }
 
@@ -386,11 +442,12 @@ cq_feature( in, out )
     struct papfile     *in, *out;
 {
     char               *start, *stop, *p;
+    int                        linelength, crlflength;
     struct comment     *comment = compeek();
     struct ppd_feature *pfe;
 
     for (;;) {
-       switch ( markline( &start, &stop, in )) {
+       switch ( markline( in, &start, &linelength, &crlflength )) {
        case 0 :
            return( 0 );
 
@@ -398,6 +455,8 @@ cq_feature( in, out )
            return( CH_MORE );
        }
 
+       stop = start + linelength;
+
        if ( comgetflags() == 0 ) {
            comsetflags( 1 );
 
@@ -420,17 +479,17 @@ cq_feature( in, out )
                return( CH_DONE );
            }
 
-           APPEND( out, pfe->pd_value, strlen( pfe->pd_value ));
-           APPEND( out, "\r", 1 );
+           append( out, pfe->pd_value, strlen( pfe->pd_value ));
+           append( out, "\r", 1 );
        } else {
            if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
                compop();
-               consumetomark( start, stop, in );
+               CONSUME( in, linelength + crlflength );
                return( CH_DONE );
            }
        }
 
-       consumetomark( start, stop, in );
+       CONSUME( in, linelength + crlflength );
     }
 }
 
@@ -440,12 +499,13 @@ static const char *prod = "*Product\n";
 cq_printer( in, out )
     struct papfile     *in, *out;
 {
-    char               *start, *stop, *p;
-    struct comment     *c, *comment = compeek();
+    char               *start, *p;
+    int                        linelength, crlflength;
+    struct comment     *comment = compeek();
     struct ppd_feature *pdpsver, *pdprod;
 
     for (;;) {
-       switch ( markline( &start, &stop, in )) {
+       switch ( markline( in, &start, &linelength, &crlflength )) {
        case 0 :
            return( 0 );
 
@@ -487,25 +547,25 @@ cq_printer( in, out )
            }
 
            /* revision */
-           APPEND( out, p + 1, strlen( p + 1 ));
-           APPEND( out, "\r", 1 );
+           append( out, p + 1, strlen( p + 1 ));
+           append( out, "\r", 1 );
 
            /* version */
-           APPEND( out, pdpsver->pd_value, p - pdpsver->pd_value );
-           APPEND( out, "\r", 1 );
+           append( out, pdpsver->pd_value, p - pdpsver->pd_value );
+           append( out, "\r", 1 );
 
            /* product */
-           APPEND( out, pdprod->pd_value, strlen( pdprod->pd_value ));
-           APPEND( out, "\r", 1 );
+           append( out, pdprod->pd_value, strlen( pdprod->pd_value ));
+           append( out, "\r", 1 );
        } else {
-           if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
+           if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) {
                compop();
-               consumetomark( start, stop, in );
+               CONSUME( in, linelength + crlflength );
                return( CH_DONE );
            }
        }
 
-       consumetomark( start, stop, in );
+       CONSUME( in, linelength + crlflength );
     }
 }
 
@@ -516,9 +576,10 @@ cq_rmjob( in, out )
     struct papfile     *in, *out;
 {
     char               *start, *stop, *p;
+    int                        linelength, crlflength;
     int                        job;
 
-    switch ( markline( &start, &stop, in )) {
+    switch ( markline( in, &start, &linelength, &crlflength )) {
     case 0 :
        return( 0 );
 
@@ -526,6 +587,8 @@ cq_rmjob( in, out )
        return( CH_MORE );
     }
 
+    stop = start + linelength;
+
     for ( p = start; p < stop; p++ ) {
        if ( *p == ' ' || *p == '\t' ) {
            break;
@@ -540,22 +603,23 @@ cq_rmjob( in, out )
     *stop = '\0';
     if ( p < stop && ( job = atoi( p )) > 0 ) {
        lp_rmjob( job );
-       APPEND( out, rmjobok, strlen( rmjobok ));
+       append( out, rmjobok, strlen( rmjobok ));
     } else {
-       APPEND( out, rmjobfailed, strlen( rmjobfailed ));
+       append( out, rmjobfailed, strlen( rmjobfailed ));
     }
 
     compop();
-    consumetomark( start, stop, in );
+    CONSUME( in, linelength + crlflength );
     return( CH_DONE );
 }
 
 cq_listq( in, out )
     struct papfile     *in, *out;
 {
-    char               *start, *stop;
+    char               *start;
+    int                        linelength, crlflength;
 
-    switch ( markline( &start, &stop, in )) {
+    switch ( markline( in, &start, &linelength, &crlflength )) {
     case 0 :
        return( 0 );
 
@@ -568,10 +632,79 @@ cq_listq( in, out )
     }
 
     compop();
-    consumetomark( start, stop, in );
+    CONSUME( in, linelength + crlflength );
     return( CH_DONE );
 }
 
+
+/*
+ * Handler for RBILogin
+ */
+
+static struct uam_obj *papd_uam = NULL;
+static const char *rbiloginok = "0\r";
+static const char *rbiloginbad = "-1\r";
+static const char *rbiloginerrstr = "%%[Error: SecurityError; \
+SecurityViolation: Unknown user, incorrect password or log on is \
+disabled ]%%\r%%Flushing: rest of job (to end-of-file) will be \
+ignored ]%%\r";
+
+cq_rbilogin( in, out )
+    struct papfile      *in, *out;
+{
+    char        *start, *stop, *p, *begin;
+    int                linelength, crlflength;
+    char        username[9] = "\0";
+    struct comment      *comment = compeek();
+    char       uamtype[20] = "\0";
+
+    for (;;) {
+        switch ( markline( in, &start, &linelength, &crlflength )) {
+        case 0 :
+            return( 0 );
+
+        case -1 :
+            return( CH_MORE );
+        }
+
+       stop = start + linelength;
+
+        if ( comgetflags() == 0 ) { /* first line */
+           begin = start + strlen(comment->c_begin);
+           p = begin;
+
+           while (*p != ' ') {
+               p++;
+           }
+
+           strncat(uamtype, begin, p - begin);
+
+           if ((papd_uam = auth_uamfind(UAM_SERVER_PRINTAUTH,
+                               uamtype, strlen(uamtype))) == NULL) {
+               syslog(LOG_INFO, "Could not find uam: %s", uamtype);
+               append(out, rbiloginbad, strlen(rbiloginbad));
+               append(out, rbiloginerrstr, strlen(rbiloginerrstr));
+           } else {
+                if ( (papd_uam->u.uam_printer(p,stop,username,out)) == 0 ) {
+                    lp_person( username );
+                } else {
+                    append(out, rbiloginbad, strlen( rbiloginbad));
+                    append(out, rbiloginerrstr, strlen(rbiloginerrstr));
+                }
+           }
+            comsetflags( 1 );
+        } else {
+            if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
+                compop();
+                return( CH_DONE );
+            }
+        }
+
+        CONSUME( in, linelength + crlflength );
+    }
+}
+
+
 /*
  * All queries start with %%?Begin and end with %%?End.  Note that the
  * "Begin"/"End" general queries have to be last.
@@ -583,6 +716,7 @@ struct comment      queries[] = {
 #endif KRB
     { "%UMICHListQueue", 0,                            cq_listq, C_FULL },
     { "%UMICHDeleteJob", 0,                            cq_rmjob,       0 },
+    { "%%?BeginQuery: RBILogin ", "%%?EndQuery",       cq_rbilogin,    0 },
     { "%%?BeginQuery",         "%%?EndQuery",          cq_query,       0 },
     { "%%?BeginFeatureQuery",  "%%?EndFeatureQuery",   cq_feature,     0 },
     { "%%?BeginFontQuery",     "%%?EndFontQuery",      cq_font,        0 },
index c58ac9a710aa16ffc0a44c46a0ae027e37ad69ec..4d73255da4f87e2b6080dbe0480e37cec211ebf0 100644 (file)
@@ -59,16 +59,16 @@ session( atp, sat )
     u_char             readport;
 
     infile.pf_state = PF_BOT;
-    infile.pf_len = 0;
+    infile.pf_bufsize = 0;
+    infile.pf_datalen = 0;
     infile.pf_buf = 0;
-    infile.pf_cur = 0;
-    infile.pf_end = 0;
+    infile.pf_data = 0;
 
     outfile.pf_state = PF_BOT;
-    outfile.pf_len = 0;
+    outfile.pf_bufsize = 0;
+    outfile.pf_datalen = 0;
     outfile.pf_buf = 0;
-    outfile.pf_cur = 0;
-    outfile.pf_end = 0;
+    outfile.pf_data = 0;
 
     /*
      * Ask for data.
@@ -170,7 +170,7 @@ session( atp, sat )
                 * If we're in the middle of a file, clean up.
                 */
                if (( infile.pf_state & PF_BOT ) ||
-                       ( PF_BUFSIZ( &infile ) == 0 &&
+                       ( infile.pf_datalen == 0 &&
                        ( infile.pf_state & PF_EOF ))) {
                    lp_print();
                } else {
@@ -219,7 +219,7 @@ session( atp, sat )
            }
 
            for ( i = 0; i < atpb.atp_rresiovcnt; i++ ) {
-               APPEND( &infile,
+               append( &infile,
                        niov[ i ].iov_base + 4, niov[ i ].iov_len - 4 );
                if (( infile.pf_state & PF_EOF ) == 0 &&
                        ((char *)niov[ 0 ].iov_base)[ 2 ] ) {
@@ -262,17 +262,17 @@ session( atp, sat )
 
        /* send any data that we have */
        if ( readpending &&
-               ( PF_BUFSIZ( &outfile ) || ( outfile.pf_state & PF_EOF ))) {
+               ( outfile.pf_datalen || ( outfile.pf_state & PF_EOF ))) {
            for ( i = 0; i < quantum; i++ ) {
                ((char *)niov[ i ].iov_base)[ 0 ] = connid;
                ((char *)niov[ i ].iov_base)[ 1 ] = PAP_DATA;
                ((char *)niov[ i ].iov_base)[ 2 ] =
                        ((char *)niov[ i ].iov_base)[ 3 ] = 0;
 
-               if ( PF_BUFSIZ( &outfile ) > PAP_MAXDATA  ) {
+               if ( outfile.pf_datalen > PAP_MAXDATA  ) {
                    cc = PAP_MAXDATA;
                } else {
-                   cc = PF_BUFSIZ( &outfile );
+                   cc = outfile.pf_datalen;
                    if ( outfile.pf_state & PF_EOF ) {
                        ((char *)niov[ 0 ].iov_base)[ 2 ] = 1;  /* eof */
                        outfile.pf_state = PF_BOT;
@@ -281,9 +281,9 @@ session( atp, sat )
                }
 
                niov[ i ].iov_len = 4 + cc;
-               bcopy( outfile.pf_cur, niov[ i ].iov_base + 4, cc );
+               bcopy( outfile.pf_data, niov[ i ].iov_base + 4, cc );
                CONSUME( &outfile, cc );
-               if ( PF_BUFSIZ( &outfile ) == 0 ) {
+               if ( outfile.pf_datalen == 0 ) {
                    i++;
                    break;
                }
diff --git a/etc/papd/uam.c b/etc/papd/uam.c
new file mode 100644 (file)
index 0000000..a7ca13a
--- /dev/null
@@ -0,0 +1,225 @@
+/* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
+ * All Rights Reserved.  See COPYRIGHT.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <syslog.h>
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <netatalk/endian.h>
+#include <atalk/asp.h>
+#include <atalk/dsi.h>
+#include <atalk/afp.h>
+#include <atalk/util.h>
+
+#include "uam_auth.h"
+
+/* --- server uam functions -- */
+
+/* uam_load. uams must have a uam_setup function. */
+struct uam_mod *uam_load(const char *path, const char *name)
+{
+  char buf[MAXPATHLEN + 1], *p;
+  struct uam_mod *mod;
+  void *module;
+
+  if ((module = mod_open(path)) == NULL) {
+    syslog(LOG_ERR, "uam_load(%s): failed to load.", name);
+    syslog(LOG_ERR, dlerror());
+    return NULL;
+  }
+
+  if ((mod = (struct uam_mod *) malloc(sizeof(struct uam_mod))) == NULL) {
+    syslog(LOG_ERR, "uam_load(%s): malloc failed", name);
+    goto uam_load_fail;
+  }
+
+  strncpy(buf, name, sizeof(buf));
+  if ((p = strchr(buf, '.')))
+    *p = '\0';
+  if ((mod->uam_fcn = mod_symbol(module, buf)) == NULL) {
+    goto uam_load_err;
+  }
+
+  if (mod->uam_fcn->uam_type != UAM_MODULE_SERVER) {
+    syslog(LOG_ERR, "uam_load(%s): attempted to load a non-server module",
+          name);
+    goto uam_load_err;
+  }
+
+  /* version check would go here */
+
+  if (!mod->uam_fcn->uam_setup || 
+      ((*mod->uam_fcn->uam_setup)(name) < 0)) {
+    syslog(LOG_ERR, "uam_load(%s): uam_setup failed", name);
+    goto uam_load_err;
+  }
+
+  mod->uam_module = module;
+  return mod;
+
+uam_load_err:
+  free(mod);
+uam_load_fail:
+  mod_close(module);
+  return NULL;
+}
+
+/* unload the module. we check for a cleanup function, but we don't
+ * die if one doesn't exist. however, things are likely to leak without one.
+ */
+void uam_unload(struct uam_mod *mod)
+{
+  if (mod->uam_fcn->uam_cleanup)
+    (*mod->uam_fcn->uam_cleanup)();
+  mod_close(mod->uam_module);
+  free(mod);
+}
+
+/* -- client-side uam functions -- */
+
+/* set up stuff for this uam. */
+int uam_register(const int type, const char *path, const char *name, ...)
+{
+  va_list ap;
+  struct uam_obj *uam;
+
+  if (!name)
+    return -1;
+
+  /* see if it already exists. */
+  if ((uam = auth_uamfind(type, name, strlen(name)))) {
+    if (strcmp(uam->uam_path, path)) {
+      /* it exists, but it's not the same module. */
+      syslog(LOG_ERR, "uam_register: \"%s\" already loaded by %s",
+            name, path);
+      return -1;
+    }
+    uam->uam_count++;
+    return 0;
+  }
+  
+  /* allocate space for uam */
+  if ((uam = calloc(1, sizeof(struct uam_obj))) == NULL)
+    return -1;
+
+  uam->uam_name = name;
+  uam->uam_path = strdup(path);
+  uam->uam_count++;
+
+  va_start(ap, name);
+  switch (type) {
+  case UAM_SERVER_LOGIN: /* expect three arguments */
+    uam->u.uam_login.login = va_arg(ap, void *);
+    uam->u.uam_login.logincont = va_arg(ap, void *);
+    uam->u.uam_login.logout = va_arg(ap, void *);
+    break;
+  case UAM_SERVER_CHANGEPW: /* one argument */
+    uam->u.uam_changepw = va_arg(ap, void *);
+    break;
+  case UAM_SERVER_PRINTAUTH: /* x arguments */
+    uam->u.uam_printer = va_arg(ap, void *);
+    break;
+  default:
+    break;
+  }
+  va_end(ap);
+
+  /* attach to other uams */
+  if (auth_register(type, uam) < 0) {
+    free(uam->uam_path);
+    free(uam);
+    return -1;
+  }
+
+  return 0;
+}
+
+void uam_unregister(const int type, const char *name)
+{
+  struct uam_obj *uam;
+
+  if (!name)
+    return;
+
+  uam = auth_uamfind(type, name, strlen(name));
+  if (!uam || --uam->uam_count > 0)
+    return;
+
+  auth_unregister(uam);
+  free(uam->uam_path);
+  free(uam);
+}
+
+/* Crap to support uams which call this afpd function */
+int uam_afpserver_option(void *private, const int what, void *option,
+                         int *len)
+{
+       return(0);
+}
+
+/* --- helper functions for plugin uams --- */
+
+struct passwd *uam_getname(char *name, const int len)
+{
+  struct passwd *pwent;
+  char *user;
+  int i;
+
+  if ((pwent = getpwnam(name)))
+    return pwent;
+
+#ifndef NO_REAL_USER_NAME
+  for (i = 0; i < len; i++)
+    name[i] = tolower(name[i]);
+
+  setpwent();
+  while ((pwent = getpwent())) {
+    if (user = strchr(pwent->pw_gecos, ','))
+      *user = '\0';
+    user = pwent->pw_gecos;
+
+    /* check against both the gecos and the name fields. the user
+     * might have just used a different capitalization. */
+    if ((strncasecmp(user, name, len) == 0) ||
+        (strncasecmp(pwent->pw_name, name, len) == 0)) {
+      strncpy(name, pwent->pw_name, len);
+      break;
+    }
+  }
+  endpwent();
+#endif
+
+  /* os x server doesn't keep anything useful if we do getpwent */
+  return pwent ? getpwnam(name) : NULL;
+}
+
+
+int uam_checkuser(const struct passwd *pwd)
+{
+  char *p;
+
+  if (!pwd || !pwd->pw_shell || (*pwd->pw_shell == '\0')) 
+    return -1;
+
+  while ((p = getusershell())) {
+    if ( strcmp( p, pwd->pw_shell ) == 0 ) 
+      break;
+  }
+  endusershell();
+
+  if (!p) {
+    syslog( LOG_INFO, "illegal shell %s for %s",pwd->pw_shell,pwd->pw_name);
+    return -1;
+  }
+
+  return 0;
+}
+
+
diff --git a/etc/papd/uam_auth.h b/etc/papd/uam_auth.h
new file mode 100644 (file)
index 0000000..bf644fc
--- /dev/null
@@ -0,0 +1,67 @@
+/* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
+ * All Rights Reserved.  See COPYRIGHT.
+ *
+ * interface between uam.c and auth.c
+ */
+
+#ifndef PAPD_UAM_AUTH_H
+#define PAPD_UAM_AUTH_H 1
+
+#include <sys/cdefs.h>
+#include <pwd.h>
+
+#include <atalk/uam.h>
+
+struct uam_mod {
+  void *uam_module;
+  struct uam_export *uam_fcn;
+  struct uam_mod *uam_prev, *uam_next;
+};
+
+struct uam_obj {
+  const char *uam_name; /* authentication method */
+  char *uam_path; /* where it's located */
+  int uam_count;
+  union {
+    struct {
+      int (*login) __P((void *, struct passwd **, 
+                       char *, int, char *, int *));
+      int (*logincont) __P((void *, struct passwd **, char *,
+                           int, char *, int *));
+      void (*logout) __P((void));
+    } uam_login;
+    int (*uam_changepw) __P((void *, char *, struct passwd *, char *,
+                            int, char *, int *));
+    int (*uam_printer) __P((char *, char *, char *, struct papfile *));
+  } u;
+  struct uam_obj *uam_prev, *uam_next;
+};
+
+#define uam_attach(a, b) do { \
+    (a)->uam_prev->uam_next = (b); \
+    (b)->uam_prev = (a)->uam_prev; \
+    (b)->uam_next = (a); \
+    (a)->uam_prev = (b); \
+} while (0)                                 
+
+#define uam_detach(a) do { \
+    (a)->uam_prev->uam_next = (a)->uam_next; \
+    (a)->uam_next->uam_prev = (a)->uam_prev; \
+} while (0)
+
+#define UAM_LIST(type) (((type) == UAM_SERVER_LOGIN) ? &uam_login : \
+                (((type) == UAM_SERVER_CHANGEPW) ? &uam_changepw : \
+                (((type) == UAM_SERVER_PRINTAUTH) ? &uam_printer : NULL)))
+
+
+extern struct uam_mod *uam_load __P((const char *, const char *));
+extern void uam_unload __P((struct uam_mod *));
+
+/* auth.c */
+int auth_load __P((const char *, const char *));
+int auth_register __P((const int, struct uam_obj *));
+#define auth_unregister(a) uam_detach(a)
+struct uam_obj *auth_uamfind __P((const int, const char *, const int));
+void auth_unload __P((void));
+
+#endif /* uam_auth.h */
index 41e2d70b3875f6c47d8148a0ba2faad9cc247261..0fe9d5cb0e0e6ee7a0a9fd5f94893410ae2d9857 100644 (file)
@@ -42,13 +42,60 @@ static int noauth_login(void *obj, struct passwd **uam_pwd,
     return( AFP_OK );
 }
 
+
+/* Printer NoAuthUAM Login */
+int noauth_printer(start, stop, username, out)
+       char    *start, *stop, *username;
+       struct papfile  *out;
+{
+    char       *data, *p, *q;
+    static const char *loginok = "0\r";
+
+    data = (char *)malloc(stop - start + 1);
+    strncpy(data, start, stop - start + 1);
+
+    /* We are looking for the following format in data:
+     * (username)
+     *
+     * Hopefully username doesn't contain a ")"
+     */
+
+    if ((p = strchr(data, '(' )) == NULL) {
+       syslog(LOG_INFO,"Bad Login NoAuthUAM: username not found in string");
+       free(data);
+       return(-1);
+    }
+    p++;
+    if ((q = strchr(data, ')' )) == NULL) {
+       syslog(LOG_INFO,"Bad Login NoAuthUAM: username not found in string");
+       free(data);
+       return(-1);
+    }
+    strncpy(username, p, q - p);
+
+    /* Done copying username, clean up */
+    free(data);
+
+    if (getpwnam(username) == NULL) {
+       syslog(LOG_INFO, "Bad Login NoAuthUAM: %s: %m", username);
+       return(-1);
+    }
+
+    /* Login successful */
+    append(out, loginok, strlen(loginok));
+    syslog(LOG_INFO, "Login NoAuthUAM: %s", username);
+    return(0);
+}
+
+
 static int uam_setup(const char *path)
 {
   if (uam_register(UAM_SERVER_LOGIN, path, "No User Authent",
               noauth_login, NULL, NULL) < 0)
-    return -1;
-  /* uam_register(UAM_SERVER_PRINTAUTH, path,
-     "No User Authent", noauth_printer); */
+       return -1;
+  if (uam_register(UAM_SERVER_PRINTAUTH, path, "NoAuthUAM",
+               noauth_printer) < 0)
+       return -1;
 
   return 0;
 }
@@ -56,7 +103,7 @@ static int uam_setup(const char *path)
 static void uam_cleanup()
 {
   uam_unregister(UAM_SERVER_LOGIN, "No User Authent");
-  /* uam_unregister(UAM_SERVER_PRINTAUTH, "No User Authent"); */
+  uam_unregister(UAM_SERVER_PRINTAUTH, "NoAuthUAM");
 }
 
 UAM_MODULE_EXPORT struct uam_export uams_guest = {
index 3475913ff363e11d7127629b2c3148929a5884cb..7b950b24ea612d44aca950487b796d86e96e4279 100644 (file)
@@ -255,20 +255,121 @@ static int pam_changepw(void *obj, char *username,
 }
 
 
+/* Printer ClearTxtUAM login */
+int pam_printer(start, stop, username, out)
+        char    *start, *stop, *username;
+       struct papfile  *out;
+{
+    int PAM_error;
+    char       *data, *p, *q;
+    char       password[PASSWDLEN + 1] = "\0";
+    static const char *loginok = "0\r";
+
+    data = (char *)malloc(stop - start + 1);
+    strncpy(data, start, stop - start + 1);
+
+    /* We are looking for the following format in data:
+     * (username) (password)
+     *
+     * Let's hope username doesn't contain ") ("!
+     */
+
+    /* Parse input for username in () */
+    if ((p = strchr(data, '(' )) == NULL) {
+       syslog(LOG_INFO,"Bad Login ClearTxtUAM: username not found in string");
+       free(data);
+       return(-1);
+    }
+    p++;
+    if ((q = strstr(data, ") (" )) == NULL) {
+       syslog(LOG_INFO,"Bad Login ClearTxtUAM: username not found in string");
+       free(data);
+       return(-1);
+    }
+    strncpy(username, p, q - p);
+
+    /* Parse input for password in next () */
+    p = q + 3;
+    if ((q = strrchr(data, ')' )) == NULL) {
+       syslog(LOG_INFO,"Bad Login ClearTxtUAM: password not found in string");
+       free(data);
+       return(-1);
+    }
+    strncpy(password, p, q - p);
+
+    /* Done copying username and password, clean up */
+    free(data);
+
+    PAM_username = username;
+    PAM_password = password;
+
+    PAM_error = pam_start("netatalk", username, &PAM_conversation,
+                          &pamh);
+    if (PAM_error != PAM_SUCCESS) {
+       syslog(LOG_INFO, "Bad Login ClearTxtUAM: %s: %s", 
+                       username, pam_strerror(pamh, PAM_error));
+        pam_end(pamh, PAM_error);
+        pamh = NULL;
+        return(-1);
+    }
+
+    pam_set_item(pamh, PAM_TTY, "papd");
+    pam_set_item(pamh, PAM_RHOST, hostname);
+    PAM_error = pam_authenticate(pamh,0);
+    if (PAM_error != PAM_SUCCESS) {
+       syslog(LOG_INFO, "Bad Login ClearTxtUAM: %s: %s", 
+                       username, pam_strerror(pamh, PAM_error));
+        pam_end(pamh, PAM_error);
+        pamh = NULL;
+        return(-1);
+    }      
+
+    PAM_error = pam_acct_mgmt(pamh, 0);
+    if (PAM_error != PAM_SUCCESS) {
+       syslog(LOG_INFO, "Bad Login ClearTxtUAM: %s: %s", 
+                       username, pam_strerror(pamh, PAM_error));
+        pam_end(pamh, PAM_error);
+        pamh = NULL;
+        return(-1);
+    }
+
+    PAM_error = pam_open_session(pamh, 0);
+    if (PAM_error != PAM_SUCCESS) {
+       syslog(LOG_INFO, "Bad Login ClearTxtUAM: %s: %s", 
+                       username, pam_strerror(pamh, PAM_error));
+        pam_end(pamh, PAM_error);
+        pamh = NULL;
+        return(-1);
+    }
+
+    /* Login successful, but no need to hang onto it,
+       so logout immediately */
+    append(out, loginok, strlen(loginok));
+    syslog(LOG_INFO, "Login ClearTxtUAM: %s", username);
+    pam_close_session(pamh, 0);
+    pam_end(pamh, 0);
+    pamh = NULL;
+
+    return(0);
+}
+
+
 static int uam_setup(const char *path)
 {
   if (uam_register(UAM_SERVER_LOGIN, path, "Cleartxt Passwrd", 
                   pam_login, NULL, pam_logout) < 0)
-    return -1;
+       return -1;
 
   if (uam_register(UAM_SERVER_CHANGEPW, path, "Cleartxt Passwrd",
                   pam_changepw) < 0) {
-    uam_unregister(UAM_SERVER_LOGIN, "Cleartxt Passwrd");
-    return -1;
+       uam_unregister(UAM_SERVER_LOGIN, "Cleartxt Passwrd");
+       return -1;
   }
 
-  /*uam_register(UAM_SERVER_PRINTAUTH, path, "Cleartxt Passwrd",
-    pam_printer);*/
+  if (uam_register(UAM_SERVER_PRINTAUTH, path, "ClearTxtUAM",
+                  pam_printer) < 0) {
+       return -1;
+  }
 
   return 0;
 }
@@ -277,7 +378,7 @@ static void uam_cleanup(void)
 {
   uam_unregister(UAM_SERVER_LOGIN, "Cleartxt Passwrd");
   uam_unregister(UAM_SERVER_CHANGEPW, "Cleartxt Passwrd");
-  /*uam_unregister(UAM_SERVER_PRINTAUTH, "Cleartxt Passwrd"); */
+  uam_unregister(UAM_SERVER_PRINTAUTH, "ClearTxtUAM");
 }
 
 UAM_MODULE_EXPORT struct uam_export uams_clrtxt = {
index 67699a973eee321b0f16a5be3f9cb356913f67e8..3d97959bfed5638524a9cf5a830cd854339666cd 100644 (file)
@@ -130,20 +130,118 @@ static int passwd_changepw(void *obj, char *username,
 }
 #endif
 
+
+/* Printer ClearTxtUAM login */
+static int passwd_printer(start, stop, username, out)
+       char    *start, *stop, *username;
+       struct papfile  *out;
+{
+    struct passwd *pwd;
+#ifdef SHADOWPW
+    struct spwd *sp;
+#endif
+    char *data, *p, *q;
+    char       password[PASSWDLEN + 1] = "\0";
+    static const char *loginok = "0\r";
+    int ulen;
+
+    data = (char *)malloc(stop - start + 1);
+    strncpy(data, start, stop - start + 1);
+
+    /* We are looking for the following format in data:
+     * (username) (password)
+     *
+     * Let's hope username doesn't contain ") ("!
+     */
+
+    /* Parse input for username in () */
+    if ((p = strchr(data, '(' )) == NULL) {
+        syslog(LOG_INFO,"Bad Login ClearTxtUAM: username not found in string");
+        free(data);
+        return(-1);
+    }
+    p++;
+    if ((q = strstr(data, ") (" )) == NULL) {
+        syslog(LOG_INFO,"Bad Login ClearTxtUAM: username not found in string");
+        free(data);
+        return(-1);
+    }
+    strncpy(username, p, q - p);
+
+    /* Parse input for password in next () */
+    p = q + 3;
+    if ((q = strrchr(data, ')' )) == NULL) {
+        syslog(LOG_INFO,"Bad Login ClearTxtUAM: password not found in string");
+       free(data);
+        return(-1);
+    }
+    strncpy(password, p, q - p);
+
+    /* Done copying username and password, clean up */
+    free(data);
+
+    ulen = strlen(username);
+
+    if (( pwd = uam_getname(username, ulen)) == NULL ) {
+       syslog(LOG_INFO, "Bad Login ClearTxtUAM: ( %s ) not found ",
+                       username);
+       return(-1);
+    }
+
+    if (uam_checkuser(pwd) < 0) {
+       /* syslog of error happens in uam_checkuser */
+       return(-1);
+    }
+
+#ifdef SHADOWPW
+    if (( sp = getspnam( pwd->pw_name )) == NULL ) {
+       syslog(LOG_INFO, "Bad Login ClearTxtUAM: no shadow passwd entry for %s", 
+                       username);
+       return(-1);
+    }
+    pwd->pw_passwd = sp->sp_pwdp;
+#endif SHADOWPW
+
+    if (!pwd->pw_passwd) {
+       syslog(LOG_INFO, "Bad Login ClearTxtUAM: no password for %s",
+                       username);
+       return(-1);
+    }
+
+#ifdef AFS
+    if ( kcheckuser( pwd, password) == 0) 
+      return(0);
+#endif AFS
+
+    p = crypt(password, pwd->pw_passwd);
+    if (strcmp(p, pwd->pw_passwd) != 0) {
+       syslog(LOG_INFO, "Bad Login ClearTxtUAM: %s: bad password", username);
+       return(-1);
+    }
+
+    /* Login successful */
+    append(out, loginok, strlen(loginok));
+    syslog(LOG_INFO, "Login ClearTxtUAM: %s", username);
+    return(0);
+}
+
+
 static int uam_setup(const char *path)
 {
-  if (uam_register(UAM_SERVER_LOGIN, path, 
-              "Cleartxt Passwrd", passwd_login, NULL, NULL) < 0)
-    return -1;
-  /*uam_register(UAM_SERVER_PRINTAUTH, path, "Cleartxt Passwrd",
-    passwd_printer);*/
+  if (uam_register(UAM_SERVER_LOGIN, path, "Cleartxt Passwrd", 
+               passwd_login, NULL, NULL) < 0)
+       return -1;
+  if (uam_register(UAM_SERVER_PRINTAUTH, path, "ClearTxtUAM",
+               passwd_printer) < 0)
+       return -1;
+
   return 0;
 }
 
 static void uam_cleanup(void)
 {
   uam_unregister(UAM_SERVER_LOGIN, "Cleartxt Passwrd");
-  /*uam_unregister(UAM_SERVER_PRINTAUTH, "Cleartxt Passwrd"); */
+  uam_unregister(UAM_SERVER_PRINTAUTH, "ClearTxtUAM");
 }
 
 UAM_MODULE_EXPORT struct uam_export uams_clrtxt = {