greater on client. See README.MORGAN for information.
--- /dev/null
+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>
+
# 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.
*buflen = 0;
return len;
}
+
+/* --- papd-specific functions (just placeholders) --- */
+void append(void *pf, char *data, int len)
+{
+ return;
+}
/*
* 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;
}
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
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
${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}
--- /dev/null
+/*
+ * 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);
+ }
+}
#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 )
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 );
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;
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 ));
}
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
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 );
return( CH_MORE );
}
+ stop = start + linelength;
for ( p = start; p < stop; p++ ) {
if ( *p == ':' ) {
break;
*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 );
}
struct papfile *out;
{
char buf[ 1024 ], *start, *stop, *p, *q;
+ int linelength, crlflength;
static struct papfile pf;
int n, len, s;
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;
}
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' ) {
}
}
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' ) {
}
}
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' ) {
}
}
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 );
}
ps( infile, outfile )
struct papfile *infile, *outfile;
{
- char *start, *stop;
+ char *start;
+ int linelength, crlflength;
struct comment *comment;
for (;;) {
}
} else {
- switch ( markline( &start, &stop, infile )) {
+ switch ( markline( infile, &start, &linelength, &crlflength )) {
case 0 :
/* eof on infile */
outfile->pf_state |= PF_EOF;
}
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 (;;) */
}
}
/* write to file */
- *stop = '\n';
- lp_write( start, stop - start + 1 );
- consumetomark( start, stop, infile );
+ lp_write( start, linelength + crlflength );
+ CONSUME( infile, linelength + crlflength );
}
}
}
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;
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;
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 );
}
}
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;
return( CH_MORE );
}
+ stop = start + linelength;
for ( p = start; p < stop; p++ ) {
if ( *p == ' ' || *p == '\t' ) {
break;
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);
}
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;
papd_exit( 1 );
}
+ /*
+ * Load UAMS
+ */
+ auth_load(uampath, uamlist);
+
/*
* Begin accepting connections.
*/
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.
* 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
#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;
#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 );
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;
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 );
}
}
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 );
}
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 ));
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,
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 );
}
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 );
}
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 );
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
struct papfile *out;
{
if ( printer->p_flags & P_SPOOLED ) {
- APPEND( out, "true\n", 5 );
+ append( out, "true\n", 5 );
return( 0 );
} else {
return( -1 );
/* 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 );
}
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)();
#ifdef notdef
{ "UMICHUserBalance", gq_balance },
#endif
+ { "RBISpoolerID", gq_rbispoolerid },
+ { "RBIUAMListQuery", gq_rbiuamlist },
{ "UMICHListQueue", gq_true },
{ "UMICHDeleteJob", gq_true },
{ NULL },
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 );
return( CH_MORE );
}
+ stop = start+linelength;
+
if ( comgetflags() == 0 ) { /* started */
comsetflags( 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 );
}
}
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 );
}
}
}
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 );
return( CH_MORE );
}
+ stop = start + linelength;
+
if ( comgetflags() == 0 ) {
comsetflags( 1 );
} 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 );
}
}
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 );
return( CH_MORE );
}
+ stop = start + linelength;
+
if ( comgetflags() == 0 ) {
comsetflags( 1 );
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 );
}
}
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 );
}
/* 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 );
}
}
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 );
return( CH_MORE );
}
+ stop = start + linelength;
+
for ( p = start; p < stop; p++ ) {
if ( *p == ' ' || *p == '\t' ) {
break;
*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 );
}
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.
#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 },
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.
* 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 {
}
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 ] ) {
/* 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;
}
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;
}
--- /dev/null
+/* 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;
+}
+
+
--- /dev/null
+/* 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 */
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;
}
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 = {
}
+/* 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;
}
{
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 = {
}
#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 = {