σ~ POPPASSD.SAVt POPPASSD.SAV#BACKUP *.* [-]POPPASSD.SAV/SAVE/LOG HALL F"?aV6.1 _CONE:: & _CONE$DKA100: V6.1 ~ *[HALL.TEMP]POPPASSD.C;1+,w.2/F 4U22,-*E0123KPWO356%a7R%a89GFHJ /* poppassd.c v2.1b */8/* Written by Joel Snyder under contract to SchlumbergerM Donated to the Public Domain by Schlumberger (David Sims 'dpsims@slb.com')> Please give credit in any modifications or re-distributions *Not* for intended re-sale */8/* poppassd - uses POP protocols to change passwords */ #define VERSION "2.1beta"/* * poppassd.c *8 * A Eudora and NUPOP change password server for OpenVMS * * Joel Snyder * Opus One) * 1404 East Lind Road, Tucson, AZ, 857191 * +1 602 324 0494 (voice); +1 602 324 0495 (FAX) * jms@opus1.com * 2/10/95 *? * Based on earlier versions by Roy Smith , Daniel0 * L. Leavitt , and John Norstad. * H * Note that unencrypted passwords are transmitted over the network. IfG * this bothers you, think hard about whether you want to implement theI * password changing feature. On the other hand, it's no worse than whatI * happens when you run /bin/passwd while connected via telnet or rlogin.I * Well, maybe it is, since the use of a dedicated port makes it slightly@ * easier for a network snooper to snarf passwords off the wire. *K * NOTE: In addition to the security issue outlined in the above paragraph,K * you should be aware that this program is going to be run with privilegesM * by ordinary users and it mucks around with the password file. This should! * set alarms off in your head.  *% * Needs to be installed privileged.  *! * Instructions for installation: *C * 0- READ THROUGH THE SOURCE TO MAKE SURE THAT THIS DOES WHAT YOU  * WANT IT TO DO ! ! !0 * 1- compile and link it properly. To do that:. * $ cc poppassd (if you have DEC C, cc/vaxc)) * $ link poppassd,sys$input:/opt/notrace0 * MULTINET:MULTINET_SOCKET_LIBRARY/SHARE  * SYS$SHARE:VAXCRTL/SHARE * ^Z7 * 2- put it somewhere. I suggest you put this in yourG * MULTINET_COMMON_ROOT:[MULTINET] directories, unless you have some> * place else where you keep images like this. To do that:; * $ copy poppassd.exe multinet_common_root:[multinet]F * 3- make Multinet know about it. To do that (assuming you stuck the$ * file in multinet:poppassd.exe: * $ multinet config/server * SERVER-CONFIG>add poppassd: * [Adding new configuration entry for service "poppassd"] * Protocol: [TCP] * TCP Port number: 106( * Program to run: MULTINET:poppassd.EXE, * [Added service poppassd to configuration]% * [Selected service is now poppassd] * SERVER-CONFIG>show/full * Ser vice "poppassd":5 * TCP socket (AF_INET,SOCK_STREAM), Port 106( * Socket Options = SO_KEEPALIVE * INIT() = TCP_Init * LISTEN() = TCP_Listen& * CONNECTED() = TCP_Connected" * SERVICE() = Run_Program, * Program = "MULTINET:poppassd.EXE" * SERVER-CONFIG>restart *  */5/* Steve Dorner's description of the simple protocol: *D * The server's responses should be like an FTP server's responses; A * 1xx for in progress, 2xx for success, 3xx for more informationF * needed, 4xx for temporary failure, and 5xx for permanent failure. 9 * Putting it all together, here's a sample conversation: * * S: 200 hello\r\n * E: user yourloginname\r\n- * S: 300 please send your password now\r\n$ * E: pass yourcurrentpassword\r\n" * S: 200 My, that was tasty\r\n# * E: newpass yournewpassword\r\n * S: 200 Happy to oblige\r\n * E: quit\r\n * S: 200 Bye-bye\r\n * S:  * E:  */#include #include #include #include ,#include /* just for isalpha() */;#include /* defines struct dsc$descriptor_s *//#include /* defines UAI$_ENCRYPT *//*9 * Not all versions of the VAX C compiler have all of theA * values we need. This is a bad idea, but the best I could come * up with. */#ifndef UAI$_PASSWORD4#define UAI$_PASSWORD 73 /* must be less than 117 */#endif/#ifdef UCX /* for future UCX compatibility */*#include /* ignore for now. */#include #include #include #endif#define BUFSIZE 5128#define MAXPWDLEN 32 /* maximum length of a password */<#define MAXUSERNAMELEN 32 /* maximum length of a username *//*@ * This program does a lot of things which a particular site may@ * want to disable or change. These are all controlled by theseA * compile-time constants. Normally, you should just leave these * be.  */N/* Uncomment the following line so we does NOT upper case username/password *//* #define NOUPCASE 1 */N/* The previous line should BE COMMENTED OUT in standard VMS operations. */H/* poppassd logs everything it does. Change this to define where you */(/* want it to send such log messages. */(#define poppassd_LOG_FILE "poppassd.log"*/* poppassd normally runs on port 106. */#define poppassd_PORT 1063typedef struct itemlist { /* VMS style itemlist */ variant_union { variant_struct {#  unsigned short buffer_length;  unsigned short item_code; } i__v_s; unsigned int end_of_itemlist; } i__v_u; char *buffer_address; ! int *return_length_address; }*ITEMLISTPTR,ITEMLIST_STRUCT; I#define TCPIP_DEVICE_TYPE "INET" /* may have to change for other ip sw */ #ifndef FALSE,#define FALSE 0 /* It is required that */*#define TRUE 1 /* True != False == 0 */#endif #ifndef NULL6#define NULL 0 /* Just in case this isn't defined */#endif8#define bool int /* for a future, superior language */C#define _toupper(c) ((c) >= 'a' && (c) <= 'z' ? (c) & 0x5F:(c)) #ifndef UCX0unsigned short lchan; /* the network channel */#elseint listenchan, lchan;#endif-static unsigned char debug; /* debug flag */4static bool TCPIP; /* set to TRUE if we're TCPIP *//* * Prototypes  */void WriteToClient( char * );void ReadFromClient( char * );void close_files ();void log_info( char * );bool chkPass (char *, char *);&bool chgPass (char *, char *, char *);void do_ucx_open ();/* * Globals for everyone to use */char because[BUFSIZE];char user[BUFSIZE]; intmain(){ char line[BUFSIZE]; char oldpass[BUFSIZE]; char newpass[BUFSIZE];/ char emess[BUFSIZE]; /* logging message */5 char word1[BUFSIZE]; /* for incoming commands */< char word2[BUFSIZE]; /* for incoming command objects */ unsigned int status;H unsigned int have_user, have_oldpass, have_newpass, prompt_for_more;@ static struct {int Size; char *Ptr;} Descr={9 ,"SYS$INPUT"}; /*. * Initialize variables, including debug mode. */$ *user = *oldpass = *newpass = 0;F prompt_for_more = have_user = have_oldpass = have_newpass = FALSE;* if (getenv("poppassd_DEBUG") != NULL)  debug = TRUE; else debug = FALSE;/*F * Open up the LOCAL poppassword channel. That's the one coming in to@ * us. Find out if we're a TCP/IP object or just running at the * command line. */ #ifndef UCX. status = SYS$ASSIGN(&Descr, &lchan, 0, 0); if (!(status&1)) { log_info("Error in assign");' return(status); /* error logging ? */ } (void) i_am_tcpobj(lchan);#else (void) do_ucx_open();#endif/*6 * Begin the dialog and remember that we know nothing. */K sprintf(emess,"200 poppassd v%s hello, what's your username?",VERSION); WriteToClient (emess);/*" * Loop until we have what we need */; while ( !have_user || !have_oldpass || !have_newpass) { if (prompt_for_more) {- WriteToClient ("300 OK. Tell me more.");A prompt_for_more = FALSE; /* put out 300 message next time */ }3 word1[0] = word2[0] = 0; /* null everything out */ ReadFromClient (line);; if (strlen(line) == 0) continue; /* no data? try again. */& sscanf (line, "%s %s", word1, word2);/* * HANDLE USER  */ if ( !strcmp(word1,"user") ) {* if (strlen(word2) > MAXUSERNAMELEN) {3 WriteToClient ("500 Your username is too long.");: log_info("Too long username given after user command."); continue; }* strncpy(user, word2, MAXUSERNAMELEN); if (strlen (user) == 0) {+ WriteToClient ("500 Username required.");4 log_info("No username given after user command."); continue; } have_user = TRUE; prompt_for_more = TRUE; continue; } /* * HANDLE OLD PASSWORD */ if ( !strcmp(word1,"pass") ) {& if (strlen (word2) > MAXPWDLEN) {7 WriteToClient ("500 Your password isn't that long.");; log_info("Tried to use a too-long password on oldpass."); continue; }( strncpy(oldpass, word2, MAXPWDLEN);! if (strlen (oldpass) == 0) {+ WriteToClient ("500 Password required.");4 log_info("No password given after pass command."); continue; } have_oldpass = TRUE; prompt_for_more = TRUE; continue; } /* * HANDLE NEW PASSWORD */# if ( !strcmp(word1, "newpass") ) {& if (strlen (word2) > MAXPWDLEN) {1 WriteToClient ("500 Pick a shorter password.");; log_info("Tried to use a too-long password on newpass."); continue; }( strncpy(newpass, word2, MAXPWDLEN);! if (strlen (newpass) == 0) {/ WriteToClient ("500 New password required.");7 log_info("No password given after newpass command."); continue; } have_newpass = TRUE; prompt_for_more = TRUE; continue; }/* * HANDLE OTHER COMMANDS */ if ( !strcmp(word1, "help") ) {0 WriteToClient ("214- Available commands:"); WriteToClient ("214- ");0 WriteToClient ("214- USER, PASS, NEWPASS");3 WriteToClient ("214- NOOP, QUIT, HELP, RSET"); WriteToClient ("214- ");9 WriteToClient ("214- Bug reports to jms@opus1.com"); WriteToClient ("214 "); continue; } if ( !strcmp(word1, "noop") ) { WriteToClient ("200 Ok."); continue; } if ( !strcmp(word1, "quit") ) {# WriteToClient ("221 Goodbye"); exit(1); } if ( !strcmp(word1, "rset") ) {5 have_user = have_newpass = have_oldpass = FALSE; WriteToClient ("250 Ok."); continue; } ! if ( !strcmp(word1, "debug") ) {/ WriteToClient ("250 Debug mode enabled.");? log_info("Some moron is trying to use debug commands..."); continue; }< WriteToClient ("500 Unknown command specified. Try HELP."); continue; }, if ( !chgPass (user, oldpass, newpass) ) {? sprintf(emess,"500 Password not changed because %s.",because);. if ( (getenv("poppassd_ANAL_MODE")) != NULL) 0 WriteToClient("500 Password not changed."); else WriteToClient (emess); log_info(emess); } else {> WriteToClient ("200 Password changed, thank you very much.");B log_info ("Password changed, thank you very much."); /* log it */ } close_files(); return;} booli_am_tcpobj(chan)unsigned short chan;/*( * Return TRUE if this is a TCP object,  * FALSE otherwise? * This subroutine also sets the global variable TCPIP so that  * other things can use it.  */{ ITEMLIST_STRUCT itemlist[4];2 unsigned int devchar, devclass, devnam_length; unsigned int status; char devnam[64]; void WriteToClient();0 TCPIP = FALSE; /* not TCPIP by default */) itemlist[0].item_code = DVI$_DEVCHAR;" itemlist[0].buffer_length = 4;* itemlist[0].buffer_address = &devchar;* itemlist[0].return_length_address = 0;< itemlist[1].item_code = DVI$_DEVNAM; /* inet is tcpip */# itemlist[1].buffer_length = 64;) itemlist[1].buffer_address = &devnam;7 itemlist[1].return_length_address = &devnam_length;* itemlist[2].item_code = DVI$_DEVCLASS;" itemlist[2].buffer_length = 4;+ itemlist[2].buffer_address = &devclass;* itemlist[2].return_length_address = 0;$ itemlist[3].end_of_itemlist = 0;( status = sys$getdviw( 0 , /* efn */ chan , 0 , /* devnam */ &itemlist , 0 , /* iosb */ 0 , /* astadr */ 0 , /* astprm */ 0 ); /* nullarg */ if (status != SS$_NORMAL) {= WriteToClient("500 Sorry, an internal error has occurred.");2 return(TCPIP); /* I don't know. Maybe false? */ }> devnam[(devnam_length>=64 ? 63 : devnam_length)] = '\000';/ if (index(devnam,TCPIP_DEVICE_TYPE) != -1)  TCPIP = TRUE; return(TCPIP);} void close_files()/* * Close all files. */{ if (TCPIP) { close(lchan); } } void log_info(arg) char *arg;/*" * Log a message to the log file.  */{- long bintim; /* the time of day it is */ FILE *logfile;G char buf[BUFSIZE]; /* an internal buffer used for scratch space */4 if (getenv("poppassd_DONT_LOG") != NULL) return;, logfile = fopen(poppassd_LOG_FILE, "a"); if (logfile <= NULL) return; time(&bintim);F fprintf(logfile, "poppassd: user %s at %s", user, ctime(&bintim));$ fprintf(logfile, "\t%s\n", arg); fclose(logfile); return;}  intindex(string,substring) char* string;char* substring;/*A * This subroutine searches for substring in string. If substring= * is found, then the return value is the offset into string.# * If not found, a -1 is returned. = * INDEX is case-insensitive and not particularily efficient. */{7 int len_string = 0; /* length of search string */5 int len_substring = 0; /* length of substring */2 int offst = 0; /* current point in string */, int i = 0; /* normal index tmp var */H if ((len_string=strlen(string))<(len_substring=strlen(substring))) { return(-1); }< for (offst=0;offst<=len_string-len_substring; offst++) {9 if (_toupper((string[offst]))!=_toupper((substring[0]))) continue; for (i=1;iint chgPass(char *username, char *password, char *newpassword){$ /* Stuff for SYS$HASH_PASSWORD */@ struct dsc$descriptor_s pwd; /* password text descriptor */B struct dsc$descriptor_s newpwd; /* new password descriptor */1 unsigned char alg; /* algorithm type */4 unsigned short salt; /* hash salt value */B struct dsc$descriptor_s usrnam; /* username text descriptor */2 unsigned long hash[2]; /* hash result */  /* Storage areas for same */H char username_buf[MAXUSERNAMELEN + 1]; /* username text buffer */@ char pwd_buf[MAXPWDLEN + 1]; /* password text buffer */4 /* Stuff for SYS$GETUAI for salt and algorithm */ ITEMLIST_STRUCT itmlst[10];& /* GETUAI validation information */ unsigned long user_flags; unsigned char min_pwd_length; /* Local variables */2 int ss_stat; /* System service ret. stat */2 int sav_stat; /* Saved ss_stat across call*/; int stored_password[2]; /* Hash value from SYSUAF */ /* External Routines */7 int strcpy(); /* Included below to avoid VAXCRTL */7 int strlen(); /* Included below to avoid VAXCRTL */ int str$upcase(); int sys$exit(); int sys$getuai(); int sys$hash_password();' /* Initiali$ze SYS$GETUAI itemlist */= usrnam.dsc$a_pointer = username; /* Given this username*/+ usrnam.dsc$w_length = strlen(username);( usrnam.dsc$b_class = DSC$K_CLASS_S;( usrnam.dsc$b_dtype = DSC$K_DTYPE_T;A pwd.dsc$a_pointer = password; /* And this password */, pwd.dsc$w_length = strlen(password);) pwd.dsc$b_class = DSC$K_CLASS_S;) pwd.dsc$b_dtype = DSC$K_DTYPE_T;D newpwd.dsc$a_pointer = newpassword; /* And this password *// newpwd.dsc$w_length = strlen(newpassword);) newpwd.dsc$b_class = DSC$K_CLASS_S;) newpwd.dsc$b_dtype = DSC$K_DTYPE_T;N itmlst[0].item_code = UAI$_ENCRYPT; /* Get the encryption */N itmlst[0].buffer_address = (char *) &alg; /* algorithm value */1 itmlst[0].buffer_length = sizeof(alg);' itmlst[0].return_length_address = 0;M itmlst[1].item_code = UAI$_SALT; /* Get the salt value */4 itmlst[1].buffer_address = (char *) &salt;2 itmlst[1].buffer_length = sizeof(salt);' itmlst[1].return_length_address = 0;U itmlst[2].item_code = UAI$_PWD; /* Get the stored */U itmlst[2].buffer_address = (char *)&stored_password;/* hashed password */= itmlst[2].buffer_length = sizeof(stored_password);' itmlst[2].return_length_address = 0;E itmlst[3].item_code = UAI$_FLAGS; /* user flags */1 itmlst[3].buffer_address = &user_flags;B itmlst[3].buffer_length = 4; /* 4 bytes */' itmlst[3].return_length_address = 0;N itmlst[4].item_code = UAI$_PWD_LENGTH;/* password min length */5 itmlst[4].buffer_address = &min_pwd_length;< itmlst[4].buffer_length = 1; /* one byte */' itmlst[4].return_length_address = 0;' itmlst[5].end_of_itemlist = 0;/*/ * Assume that any error will be a system error *// strcpy (because,"a system error occurred");C /* Canonicalize username and password into upper case, just likeH LOGINOUT does. This restriction may be lifted in a future version< of VMS. If that is the case, define NOUPCASE above */#ifndef NOUPCASE* ss_stat = str$upcase(&usrnam,&usrnam);& if (!(ss_stat & 1)) return(FALSE);$ ss_stat = str$upcase(&pwd,&pwd);& if (!(ss_stat & 1)) return(FALSE);* ss_stat = str$upcase(&newpwd,&newpwd);& if (!(ss_stat & 1)) return(FALSE);#endif /* NOUPCASE */* /* Get start values from UAF record */+ ss_stat = sys$getuai(0, /* nullarg */ 0, /* nullarg */ &usrnam, /* usrnam */ &itmlst, /* itmlst */ 0, /* nullarg */ 0, /* nullarg */ 0); /* nullarg */& if (!(ss_stat & 1)) return(FALSE);= ss_stat = sys$hash_password(&pwd,alg,salt,&usrnam,&hash);& if (!(ss_stat & 1)) return(FALSE);' /* Gee... let's see if he lied! */, if ( (hash[0] == stored_password[0]) &&, (hash[1] == stored_password[1])) { ; } else {1 strcpy(because,"old password did not validate");0 return(FALSE); /* password validation error */ }/*> * We know that the old password was good. Now make sure that> * the new password is also good. We have to check a bunch of * things. */6 if ( (getenv("poppassd_IGNORE_LENGTH")) == NULL) {* if ( (strlen(newpassword) > MAXPWDLEN) ||7 (strlen(newpassword) < min_pwd_length) ) {6 strcpy(because,"password too long or too short"); return(FALSE); } }D if ( !strcmp(password,newpassword) ) { /* are they the same ? */; strcpy(because,"new password must be different from old"); return(FALSE); }7 if ( (getenv("poppassd_IGNORE_CAPTIVE")) == NULL) {$ if ( user_flags & UAI$M_CAPTIVE ) {F strcpy(because,"captive accounts cannot change their passwords"); return(FALSE); } }7 if ( (getenv("poppassd_IGNORE_DISUSER")) == NULL) {$ if ( user_flags & UAI$M_DISACNT ) {H strcpy(because,"DISUSERed accounts cannot change their passwords"); return(FALSE); } }6 if ( (getenv("poppassd_IGNORE_GENPWD")) == NULL) {# if ( user_flags & UAI$M_GENPWD ) {G strcpy(because,"password must be system generated (GENPWD flag)"); return(FALSE); } }7 if ( (getenv("poppassd_IGNORE_LOCKPWD")) == NULL) {$ if ( user_flags & UAI$M_LOCKPWD ) {6 strcpy(because,"password is locked from change"); return(FALSE); } }B/* The following does not work under all versions of 5.0 of VMS */#ifdef UAI$M_RESTRICTED : if ( (getenv("poppassd_IGNORE_RESTRICTED")) == NULL) {' if ( user_flags & UAI$M_RESTRICTED ) {I strcpy(because,"restricted accounts cannot change their passwords"); return(FALSE); } }#endif /* uai$m_restricted *//*2 * Everything seems to be cool. Set the password. */L itmlst[0].item_code = UAI$_PASSWORD; /* set the password */H itmlst[0].buffer_address = newpassword; /* password text */9 itmlst[0].buffer_length = strlen(newpassword);' itmlst[0].return_length_address = 0;' itmlst[1].end_of_itemlist = 0;* ss_stat = sys$setuai(0, /* nullarg */ 0, /* nullarg */ &usrnam, /* usrnam */ &itmlst, /* itmlst */ 0, /* nullarg */ 0, /* nullarg */ 0); /* nullarg */% if (!(ss_stat & 1)) return(FALSE); return(TRUE); } #ifdef UCXvoid do_ucx_open(){*static struct sockaddr_in listenchan_name;struct hostent hostentstruct;struct hostent *hostentptr;static char hostname[256]; int flag; int retval;int namelength;*/* Do a long and verbose UCX open, ick. */)/* Doesn't work under Multinet anyway. */B if ( (listenchan = socket (AF_INET, SOCK_STREAM, 0) ) == -1) { perror("socket"); exit(1); }/* * Get the local host name  */4 retval = gethostname(hostname, sizeof hostname); if (retval) { perror("gethostname"); exit(1); }/*( * Get pointer to network data structure */: if ( (hostentptr = gethostbyname(hostname)) == NULL) { perror("gethostbyname"); exit(1); }/*$ * Copy hostent data to safe storage */ hostentstruct = *hostentptr;/*4 * Fill in the name & address for the listen socket  */: listenchan_name.sin_family = hostentstruct.h_addrtype;4 listenchan_name.sin_port = htons(poppassd_PORT);K listenchan_name.sin_addr = * ((struct in_addr *) hostentstruct.h_addr);/* * Bind name to socket */I retval = bind (listenchan, &listenchan_name, sizeof listenchan_name); if (retval) { perror("bind"); exit(1); }/*- * Listen on socket for incoming connections  */$ retval = listen (listenchan, 2); if (retval) { perror("listen"); exit(1); }/*$ * Accept connection from the socket */* namelength = sizeof (listenchan_name);? lchan = accept (listenchan, &listenchan_name, &namelength); if (lchan == -1) { perror("accept"); exit (1); } TCPIP = TRUE; return;}#endif /* UCX */*[HALL.TEMP]POPPASSD.MAK;1+,=x./F 4L-*E0123KPWO56be%a7{%a89GFHJ-! Sample make file (poppassd.com or make.com)7! Written by Joel Snyder under contract to SchlumbergerL! Donated to the Public Domain by Schlumberger (David Sims 'dpsims@slb.com')=! Please give credit in any modifications or re-distributions! *Not* for re-sale $ cc poppassd&$ link poppassd,sys$input:/opt/notrace( multinet:multinet_socket_library/share sys$share:vaxcrtl/share*[HALL.TEMP]POPPASSD.TXT;1+,x./F 4O 6-*E0123KPWO56׌%a7r4%a89GFHJN******************************************************************************)System Manager's Notes: poppassd v2.1beta9*** Written by Joel Snyder under contract to SchlumbergerO*** Donated to the Public Domain by Schlumberger (David Sims 'dpsims@slb.com')?*** Please give credit on any modifications or re-distributions*** *Not* for re-saleInstallation Instructions=========================@0- READ THROUGH THE SOURCE TO MAKE SURE THAT THIS DOES WHAT YOU  WANT IT TO DO ! ! !F1- Compile and link it properly. To do that, create a .com file which contains the following:+$ cc poppassd (if you have DEC C, cc/vaxc)&$ link poppassd,sys$input:/opt/notrace( MULTINET:MULTINET_SOCKET_LIBRARY/SHARE SYS$SHARE:VAXCRTL/SHARE42- Put it somewhere. I suggest you put this in yourD MULTINET_COMMON_ROOT:[MULTINET] directories, unless you have some; place else where you keep images like this. To do that:3$ copy poppassd.exe multinet_common_root:[multinet]C3- make Multinet know about it. To do that (assuming you stuck the" file in multinet:poppassd.exe):$ multinet config/serverSERVER-CONFIG>add poppassd7[Adding new configuration entry for service "poppassd"]Protocol: [TCP]TCP Port number: 106%Program to run: MULTINET:poppassd.EXE)[Added service poppassd to configuration]"[Selected service is now poppassd]SERVER-CONFIG>show/fullService "poppassd":3 TCP socket (AF_INET,SOCK_STREAM), Port 106& Socket Options = SO_KEEPALIVE INIT() = TCP_Init LISTEN() = TCP_Listen$ CONNECTED() = TCP_Connected SERVICE() = Run_Program* Program = "MULTINET:poppassd.EXE"SERVER-CONFIG>restartThings you can customize========================CPOP Passwd's behavior can be changed using a variety of system-wideClogical names. The poppassd_LOG_FILE logical name must be defined.=It is currently defined as 'poppassd.log'. Or you must defineKpoppassd_DONT_LOG so that poppassd won't write log files (not recommended).Apoppassd_LOG_FILE This should be defined to point to the location> where poppassd will log everything that happens. By default,< (assuming that you have followed the other instructions and3 recommendations) this code will write the log as: - MULTINET_COMMON_ROOT:[MULTINET]poppassd.log.Apoppassd_DONT_LOG Normally, poppassd logs everything, both errorsC and successes, to a log file. This is usually a pretty good idea.< However, if you do not want poppassd to leave any traces ofC what it has done (including attempted breakins!), then define this( logical name and it will do no logging.Apoppassd_DEBUG You normally would have no reason to define this.; However, if you do, then poppassd will babble all sorts ofC interesting debugging information. Defining this logical does NOT= introduce any security problems; all it does is increase the@ amount of logging to the screen which poppassd will do. If youA define this logical name, then it is likely that Eudora will not be able to talk to poppassd.Apoppassd_ANAL_MODE Normally, poppassd is pretty chatty with users@ about why it was unable to change their password. It will tell> them if a particular username is valid, if they have given an? incorrect password, or if there is a syntax error. Some sites@ may not like the idea of this much information being given out.8 If you define poppassd_ANAL_MODE, then poppassd is very< tight-lipped about the error messages which it gives to the5 client. This does not affect the log files, though.Gpoppassd_IGNORE_LENGTH Normally, poppassd pays attention to the minimumA length of password field in each user's UAF entry. If, for some? very strange reason, you do NOT want poppassd to do this, then9 define this logical name. This is strongly discouraged!?poppassd_IGNORE_CAPTIVE Normally, poppassd will not allow users= who have the CAPTIVE flag in their UAF entry to change their< password. If you would like to allow these users to change0 their passwords, then define this logical name.?poppassd_IGNORE_DISUSER Normally, poppassd will not allow users= who have the DISUSER flag in their UAF entry to change their< password. If you would like to allow these users to changeB their passwords, then define this logical name. This is strongly discouraged!?poppassd_IGNORE_GENPWD Normally, poppassd will not allow users< who have the GENPWD flag in their UAF entry to change their< password. If you would like to allow these users tw~ POPPASSD.SAVx*E[HALL.TEMP]POPPASSD.TXT;1O o change9 their passwords, then define this logical name. This is strongly discouraged!?poppassd_IGNORE_LOCKPWD Normally, poppassd will not allow users= who have the LOCKPWD flag in their UAF entry to change their< password. If you would like to allow these users to change9 their passwords, then define this logical name. This is strongly discouraged!Bpoppassd_IGNORE_RESTRICTED Normally, poppassd will not allow users@ who have the RESTRICTED flag in their UAF entry to change their< password. If you would like to allow these users to change2 their passwords, then define this logical name. Internals of the protocol=========================3 Steve Dorner's description of the simple protocol:B The server's responses should be like an FTP server's responses; ? 1xx for in progress, 2xx for success, 3xx for more informationD needed, 4xx for temporary failure, and 5xx for permanent failure. 7 Putting it all together, here's a sample conversation: S: 200 hello\r\n E: user yourloginname\r\n+ S: 300 please send your password now\r\n" E: pass yourcurrentpassword\r\n S: 200 My, that was tasty\r\n! E: newpass yournewpassword\r\n S: 200 Happy to oblige\r\n E: quit\r\n S: 200 Bye-bye\r\n S:  E: vߙx*E[HALL.TEMP]POPPASSD.TXT;1O n!oh`n7*iPH';!G!a&Bsqw-3'8ypTBKD?H;9!5p5;:7?.1F0 :eA-""" $T (?lIS 6 )STvokgyyfdaseoWgX?potta{s2igvIO[E jm@ DopKaay' /,?>$W7/aFY\V$nctvWB]kw-usrs= }hm gaje the O@KPWD flag in uiriX  l)@ 74p)?o38 =4!7STkr+< va_sd/ $IH Kou soZlq *iKetm"4lloE thWsI users to change9 rhHiX55`ssuoBds"tYen eeTina Ghis lmg"c!n1me/ wThmsoi@ sArnnolO rFaoeS!%pisKd_IGNORE_ZEjTRICTED Nkr*ayl?,"p'pqs. ll not allo}$usersA who hwvJ T P"$ '6g t3vWAMQn^H2T!$(T8EOs  EU R_ogO sC! U R !dLI/ NELWT E#BR7OI HG6Qhe GS[3  sN` ]C@@c_lNA= KASe ~i? T   tpoSNROOXYTNIOT_HITRSN= *}oTyT- B^TC@n Wf^HO ]R O O! EjiL_R*\UN+NPxQ FERDUFM$Tl L'J cuC#XI/= ILV]U EoGOTCTRZEAWSUGAE CFUVNCSWD[O]4 0'9{x0 HOL/23uo1CO(0 UYE@H_ZKYmgIDQaMO|0=NdONs_AA\YELI DBO'YP2RXR72 )@eFu [NsyO_R/[R>SK r5ReOR4 Q^Dm3CHH/RDZbsTS|rn*nO1_ AE  A ./NaoeTR2TS_YDT-PEOTL+... iFgE Q/R>ahERSsCOGT* FB.|bvuTW;_TTO EINl|mENTeNHYc%oSOSP I _ngi feature. On the other hand, it's no worse than whatI * happens when you run /bin/passwd while connected via telnet or rlogin.I * Well, maybe it is, since the use of a dedicated port makes it slitly@ * easier for a network snooper to snarf passwords off the wire. *K * NOTE: In addition to the security issue outlined in the above paragraph,K * you should be aware that this program is going to be run with privilegesM * by ordinary users and it mucks around with the password file. This should! * set alarms off in your head.  *% * Needs to be installed privileged.  *! * Instructions for installation: *C * 0- READ THROUGH THE SOURCE TO MAKE SURE THAT THIS DOES WHAT YOU  * WANT IT TO DO ! ! !0 * 1- compile and link it properly. To do that:. * $ cc poppassd (if you have DEC C, cc/vaxc)) * $ link poppassd,sys$input:/opt/notrace0 * MULTINET:MULTINET_SOCKET_LIBRARY/SHARE  * SYS$SHARE:VAXCRTL/SHARE * ^Z7 * 2- put it somewhere. I suggest you put this in yourG * MULTINET_COMMON_ROOT:[MULTINET] directories, unless you have some> * place else where you keep images like this. To do that:; * $ copy poppassd.exe multinet_common_root:[multinet]F * 3- make Multinet know about it. To do that (assuming you stuck the$ * file in multinet:poppassd.exe: * $ multinet config/server * SERVER-CONFIG>add poppassd: * [Adding new configuration entry for service "poppassd"] * Protocol: [TCP] * TCP Port number: 106( * Program to run: MULTINET:poppassd.EXE, * [Added service poppassd to configuration]% * [Selected service is now poppassd] * SERVER-CONFIG>show/full * Ser vice "poppassd":5 * TCP socket (AF_INET,SOCK_STREAM), Port 106( * Socket Options = SO_KEEPALIVE * INIT() = TCP_Init * LISTEN() = TCP_Listen& * CONNECTED() = TCP_Connected" * SERVICE() = Run_Program, * Program = "MULTINET:poppassd.EXE" * SERVER-CONFIG>restart *  */5/* Steve Dorner's description of the simple protocol: *D * The server's responses should be like an FTP server's responses; A * 1xx for in progress, 2xx for success, 3xx for more informationF * needed, 4xx for temporary failure, and 5xx for permanent failure. 9 * Putting it all together, here's a sample conversation: * * S: 200 hello\r\n * E: user yourloginname\r\n- * S: 300 please send your password now\r\n$ * E: pass yourcurrentpassword\r\n" * S: 200 My, that was tasty\r\n# * E: newpass yournewpassword\r\n * S: 200 Happy to oblige\r\n * E: quit\r\n * S: 200 Bye-bye\r\n * S:  * E:  */#include #include #include #include ,#include /* just for isalpha() */;#include /* defines struct dsc$descriptor_s *//#include /* defines UAI$_ENCRYPT *//*9 * Not all versions of the VAX C compiler have all of theA * values we need. This is a bad idea, but the best I could come * up with. */#ifndef UAI$_PASSWORD4#define UAI$_PASSWORD 73 /* must be less than 117 */#endif/#ifdef UCX /* for future UCX compatibility */*#include /* ignore for now. */#include #include #include #endif#define BUFSIZE 5128#define MAXPWDLEN 32 /* maximum length of a password */<#define MAXUSERNAMELEN 32 /* maximum length of a username *//*@ * This program does a lot of things which a particular site may@ * want to disable or change. These are all controlled by theseA * compile-time constants. Normally, you should just leave these * be.  */N/* Uncomment the following line so we does NOT upper case username/password *//* #define NOUPCASE 1 */N/* The previous line should BE COMMENTED OUT in standard VMS operations. */H/* poppassd logs everything it does. Change this to define where you */(/* want it to send such log messages. */(#define poppassd_LOG_FILE "poppassd.log"*/* poppassd normally runs on port 106. */#define poppassd_PORT 1063typedef struct itemlist { /* VMS style itemlist */ variant_union { variant_struct {#  unsigned short buffer_length;  unsigned short item_code; } i__v_s; unsigned int end_of_itemlist; } i__v_u; char *buffer_address; ! int *return_length_address; }*ITEMLISTPTR,ITEMLIST_STRUCT; I#define TCPIP_DEVICE_TYPE "INET" /* may have to change for other ip sw */ #ifndef FALSE,#define FALSE 0 /* It is required that */*#define TRUE 1 /* True != False == 0 */#endif #ifndef NULL6#define NULL 0 /* Just in case this isn't defined */#endif8#define bool int /* for a future, superior language */C#define _toupper(c) ((c) >= 'a' && (c) <= 'z' ? (c) & 0x5F:(c)) #ifndef UCX0unsigned short lchan; /* the network channel */#elseint listenchan, lchan;#endif-static unsigned char debug; /* debug flag */4static bool TCPIP; /* set to TRUE if we're TCPIP *//* * Prototypes  */void WriteToClient( char * );void ReadFromClient( char * );void close_files ();void log_info( char * );bool chkPass (char *, char *);&bool chgPass (char *, char *, char *);void do_ucx_open ();/* * Globals for everyone to use */char because[BUFSIZE];char user[BUFSIZE]; intmain(){ char line[BUFSIZE]; char oldpass[BUFSIZE]; char newpass[BUFSIZE];/ char emess[BUFSIZE]; /* logging message */5 char word1[BUFSIZE]; /* for incoming commands */< char word2[BUFSIZE]; /* for incoming command objects */ unsigned int status;H unsigned int have_user, have_oldpass, have_newpass, prompt_for_more;@ static struct {int Size; char *Ptr;} Descr={9 ,"SYS$INPUT"}; /*. * Initialize variables, including debug mode. */$ *user = *oldpass = *newpass = 0;F prompt_for_more = have_user = have_oldpass = have_newpass = FALSE;* if (getenv("poppassd_DEBUG") != NULL)  debug = TRUE; else debug = FALSE;/*F * Open up the LOCAL poppassword channel. That's the one coming in to@ * us. Find out if we're a TCP/IP object or just running at the * command line. */ #ifndef UCX. status = SYS$ASSIGN(&Descr, &lchan, 0, 0); if (!(status&1)) { log_info("Error in assign");' return(status); /* error logging ? */ } (void) i_am_tcpobj(lchan);#else (void) do_ucx_open();#endif/*6 * Begin the dialog and remember that we know nothing. */K sprintf(emess,"200 poppassd v%s hello, what's your username?",VERSION); WriteToClient (emess);/*" * Loop until we have what we need */; while ( !have_user || !have_oldpass || !have_newpass) { if (prompt_for_more) {- WriteToClient ("300 OK. Tell me more.");A prompt_for_more = FALSE; /* put out 300 message next time */ }3 word1[0] = word2[0] = 0; /* null everything out */ ReadFromClient (line);; if (strlen(line) == 0) continue; /* no data? try again. */& sscanf (line, "%s %s", word1, word2);/* * HANDLE USER  */ if ( !strcmp(word1,"user") ) {* if (strlen(word2) > MAXUSERNAMELEN) {3 WriteToClient ("500 Your username is too long.");: log_info("Too long username given after user command."); continue; }* strncpy(user, word2, MAXUSERNAMELEN); if (strlen (user) == 0) {+ WriteToClient ("500 Username required.");4 log_info("No username given after user command."); continue; } have_user = TRUE; prompt_for_more = TRUE; continue; } /* * HANDLE OLD PASSWORD */ if ( !strcmp(word1,"pass") ) {& if (strlen (word2) > MAXPWDLEN) {7 WriteToClient ("500 Your password isn't that long.");; log_info("Tried to use a too-long password on oldpass."); continue; }( strncpy(oldpass, word2, MAXPWDLEN);! if (strlen (oldpass) == 0) {+ WriteToClient ("500 Password required.");4 log_info("No password given after pass command."); continue; } have_oldpass = TRUE; prompt_for_more = TRUE; continue; } /* * HANDLE NEW PASSWORD */# if ( !strcmp(word1, "newpass") ) {& if (strlen (word2) > MAXPWDLEN) {1 WriteToClient ("500 Pick a shorter password.");; log_info("Tried to use a too-long password on newpass."); continue; }( strncpy(newpass, word2, MAXPWDLEN);! if (strlen (newpass) == 0) {/ WriteToClient ("500 New password required.");7 log_info("No password given after newpass command."); continue; } have_newpass = TRUE; prompt_for_more = TRUE; continue; }/* * HANDLE OTHER COMMANDS */ if ( !strcmp(word1, "help") ) {0 WriteToClient ("214- Available commands:"); WriteToClient ("214- ");0 WriteToClient ("214- USER, PASS, NEWPASS");3 WriteToClient ("214- NOOP, QUIT, HELP, RSET"); WriteToClient ("214- ");9 WriteToClient ("214- Bug reports to jms@opus1.com"); WriteToClient ("214 "); continue; } if ( !strcmp(word1, "noop") ) { WriteToClient ("200 Ok."); continue; } if ( !strcmp(word1, "quit") ) {# WriteToClient ("221 Goodbye"); exit(1); } if ( !strcmp(word1, "rset") ) {5 have_user = have_newpass = have_oldpass = FALSE; WriteToClient ("250 Ok."); continue; } ! if ( !strcmp(word1, "debug") ) {/ WriteToClient ("250 Debug mode enabled.");? log_info("Some moron is trying to use debug commands..."); continue; }< WriteToClient ("500 Unknown command specified. Try HELP."); continue; }, if ( !chgPass (user, oldpass, newpass) ) {? sprintf(emess,"500 Password not changed because %s.",because);. if ( (getenv("poppassd_ANAL_MODE")) != NULL) 0 WriteToClient("500 Password not changed."); else WriteToClient (emess); log_info(emess); } else {> WriteToClient ("200 Password changed, thank you very much.");B log_info ("Password changed, thank you very much."); /* log it */ } close_files(); return;} booli_am_tcpobj(chan)unsigned short chan;/*( * Return TRUE if this is a TCP object,  * FALSE otherwise? * This subroutine also sets the global variable TCPIP so that  * other things can use it.  */{ ITEMLIST_STRUCT itemlist[4];2 unsigned int devchar, devclass, devnam_length; unsigned int status; char devnam[64]; void WriteToClient();0 TCPIP = FALSE; /* not TCPIP by default */) itemlist[0].item_code = DVI$_DEVCHAR;" itemlist[0].buffer_length = 4;* itemlist[0].buffer_address = &devchar;* itemlist[0].return_length_address = 0;< itemlist[1].item_code = DVI$_DEVNAM; /* inet is tcpip */# itemlist[1].buffer_length = 64;) itemlist[1].buffer_address = &devnam;7 itemlist[1].return_length_address = &devnam_length;* itemlist[2].item_code = DVI$_DEVCLASS;" itemlist[2].buffer_length = 4;+ itemlist[2].buffer_address = &devclass;* itemlist[2].return_length_address = 0;$ itemlist[3].end_of_itemlist = 0;( status = sys$getdviw( 0 , /* efn */ chan , 0 , /* devnam */ &itemlist , 0 , /* iosb */ 0 , /* astadr */ 0 , /* astprm */ 0 ); /* nullarg */ if (status != SS$_NORMAL) {= WriteToClient("500 Sorry, an internal error has occurred.");2 return(TCPIP); /* I don't know. Maybe false? */ }> devnam[(devnam_length>=64 ? 63 : devnam_length)] = '\000';/ if (index(devnam,TCPIP_DEVICE_TYPE) != -1)  TCPIP = TRUE; return(TCPIP);} void close_files()/* * Close all files. */{ if (TCPIP) { close(lchan); } } void log_info(arg) char *arg;/*" * Log a message to the log file.  */{- long bintim; /* the time of day it is */ FILE *logfile;G char buf[BUFSIZE]; /* an internal buffer used for scratch space */4 if (getenv("poppassd_DONT_LOG") != NULL) return;, logfile = fopen(poppassd_LOG_FILE, "a"); if (logfile <= NULL) return; time(&bintim);F fprintf(logfile, "poppassd: user %s at %s", user, ctime(&bintim));$ fprintf(logfile, "\t%s\n", arg); fclose(logfile); return;}  intindex(string,substring) char* string;char* substring;/*A * This subroutine searches for substring in string. If substring= * is found, then the return value is the offset into string.# * If not found, a -1 is returned. = * INDEX is case-insensitive and not particularily efficient. */{7 int len_string = 0; /* length of search string */5 int len_substring = 0; /* length of substring */2 int offst = 0; /* current point in string */, int i = 0; /* normal index tmp var */H if ((len_string=strlen(string))<(len_substring=strlen(substring))) { return(-1); }< for (offst=0;offst<=len_string-len_substring; offst++) {9 if (_toupper((string[offst]))!=_toupper((substring[0]))) continue; for (i=1;iint chgPass(char *username, char *password, char *newpassword){$ /* Stuff for SYS$HASH_PASSWORD */@ struct dsc$descriptor_s pwd; /* password text descriptor */B struct dsc$descriptor_s newpwd; /* new password descriptor */1 unsigned char alg; /* algorithm type */4 unsigned short salt; /* hash salt value */B struct dsc$descriptor_s usrnam; /* username text descriptor */2 unsigned long hash[2]; /* hash result */  /* Storage areas for same */H char username_buf[MAXUSERNAMELEN + 1]; /* username text buffer */@ char pwd_buf[MAXPWDLEN + 1]; /* password text buffer */4 /* Stuff for SYS$GETUAI for salt and algorithm */ ITEMLIST_STRUCT itmlst[10];& /* GETUAI validation information */ unsigned long user_flags; unsigned char min_pwd_length; /* Local variables */2 int ss_stat; /* System service ret. stat */2 int sav_stat; /* Saved ss_stat across call*/; int stored_password[2]; /* Hash value from SYSUAF */ /* External Routines */7 int strcpy(); /* Included below to avoid VAXCRTL */7 int strlen(); /* Included below to avoid VAXCRTL */ int str$upcase(); int sys$exit(); int sys$getuai(); int sys$hash_password();' /* Initiali$ze SYS$GETUAI itemlist */= usrnam.dsc$a_pointer = username; /* Given this username*/+ usrnam.dsc$w_length = strlen(username);( usrnam.dsc$b_class = DSC$K_CLASS_S;( usrnam.dsc$b_dtype = DSC$K_DTYPE_T;A pwd.dsc$a_pointer = password; /* And this password */, pwd.dsc$w_length = strlen(password);) pwd.dsc$b_class = DSC$K_CLASS_S;) pwd.dsc$b_dtype = DSC$K_DTYPE_T;D newpwd.dsc$a_pointer = newpassword; /* And this password *// newpwd.dsc$w_length = strlen(newpassword);) newpwd.dsc$b_class = DSC$K_CLASS_S;) newpwd.dsc$b_dtype = DSC$K_DTYPE_T;N itmlst[0].item_code = UAI$_ENCRYPT; /* Get the encryption */N itmlst[0].buffer_address = (char *) &alg; /* algorithm value */1 itmlst[0].buffer_length = sizeof(alg);' itmlst[0].return_length_address = 0;M itmlst[1].item_code = UAI$_SALT; /* Get the salt value */4 itmlst[1].buffer_address = (char *) &salt;2 itmlst[1].buffer_length = sizeof(salt);' itmlst[1].return_length_address = 0;U itmlst[2].item_code = UAI$_PWD; /* Get the stored */U itmlst[2].buffer_address = (char *)&stored_password;/* hashed password */= itmlst[2].buffer_length = sizeof(stored_password);' itmlst[2].return_length_address = 0;E itmlst[3].item_code = UAI$_FLAGS; /* user flags */1 itmlst[3].buffer_address = &user_flags;B itmlst[3].buffer_length = 4; /* 4 bytes */' itmlst[3].return_length_address = 0;N itmlst[4].item_code = UAI$_PWD_LENGTH;/* password min length */5 itmlst[4].buffer_address = &min_pwd_length;< itmlst[4].buffer_length = 1; /* one byte */' itmlst[4].return_length_address = 0;' itmlst[5].end_of_itemlist = 0;/*/ * Assume that any error will be a system error *// strcpy (because,"a system error occurred");C /* Canonicalize username and password into upper case, just likeH LOGINOUT does. This restriction may be lifted in a future version< of VMS. If that is the case, define NOUPCASE above */#ifndef NOUPCASE* ss_stat = str$upcase(&usrnam,&usrnam);& if (!(ss_stat & 1)) return(FALSE);$ ss_stat = str$upcase(&pwd,&pwd);& if (!(ss_stat & 1)) return(FALSE);* ss_stat = str$upcase(&newpwd,&newpwd);& if (!(ss_stat & 1)) return(FALSE);#endif /* NOUPCASE */* /* Get start values from UAF record */+ ss_stat = sys$getuai(0, /* nullarg */ 0, /* nullarg */ &usrnam, /* usrnam */ &itmlst, /* itmlst */ 0, /* nullarg */ 0, /* nullarg */ 0); /* nullarg */& if (!(ss_stat & 1)) return(FALSE);= ss_stat = sys$hash_password(&pwd,alg,salt,&usrnam,&hash);& if (!(ss_stat & 1)) return(FALSE);' /* Gee... let's see if he lied! */, if ( (hash[0] == stored_password[0]) &&, (hash[1] == stored_password[1])) { ; } else {1 strcpy(because,"old password did not validate");0 return(FALSE); /* password validation error */ }/*> * We know that the old password was good. Now make sure that> * the new password is also good. We have to check a bunch of * things. */6 if ( (getenv("poppassd_IGNORE_LENGTH")) == NULL) {* if ( (strlen(newpassword) > MAXPWDLEN) ||7 (strlen(newpassword) < min_pwd_length) ) {6 strcpy(because,"password too long or too short"); return(FALSE); } }D if ( !strcmp(password,newpassword) ) { /* are they the same ? */; strcpy(because,"new password must be different from old"); return(FALSE); }7 if ( (getenv("poppassd_IGNORE_CAPTIVE")) == NULL) {$ if ( user_flags & UAI$M_CAPTIVE ) {F strcpy(because,"captive accounts cannot change their passwords"); return(FALSE); } }7 if ( (getenv("poppassd_IGNORE_DISUSER")) == NULL) {$ if ( user_flags & UAI$M_DISACNT ) {H strcpy(because,"DISUSERed accounts cannot change their passwords"); return(FALSE); } }6 if ( (getenv("poppassd_IGNORE_GENPWD")) == NULL) {# if ( user_flags & UAI$M_GENPWD ) {G strcpy(because,"password must be system generated (GENPWD flag)"); return(FALSE); } }7 if ( (getenv("poppassd_IGNORE_LOCKPWD")) == NULL) {$ if ( user_flags & UAI$M_LOCKPWD ) {6 strcpy(because,"password is locked from change"); return(FALSE); } }B/* The following does not work under all versions of 5.0 of VMS */#ifdef UAI$M_RESTRICTED : if ( (getenv("poppassd_IGNORE_RESTRICTED")) == NULL) {' if ( user_flags & UAI$M_RESTRICTED ) {I strcpy(because,"restricted accounts cannot change their passwords"); return(FALSE); } }#endif /* uai$m_restricted *//*2 * Everything seems to be cool. Set the password. */L itmlst[0].item_code = UAI$_PASSWORD; /* set the password */H itmlst[0].buffer_address = newpassword; /* password text */9 itmlst[0].buffer_length = strlen(newpassword);' itmlst[0].return_length_address = 0;' itmlst[1].end_of_itemlist = 0;* ss_stat = sys$setuai(0, /* nullarg */ 0, /* nullarg */ &usrnam, /* usrnam */ &itmlst, /* itmlst */ 0, /* nullarg */ 0, /* nullarg */ 0); /* nullarg */% if (!(ss_stat & 1)) return(FALSE); return(TRUE); } #ifdef UCXvoid do_ucx_open(){*static struct sockaddr_in listenchan_name;struct hostent hostentstruct;struct hostent *hostentptr;static char hostname[256]; int flag; int retval;int namelength;*/* Do a long and verbose UCX open, ick. */)/* Doesn't work under Multinet anyway. */B if ( (listenchan = socket (AF_INET, SOCK_STREAM, 0) ) == -1) { perror("socket"); exit(1); }/* * Get the local host name  */4 retval = gethostname(hostname, sizeof hostname); if (retval) { perror("gethostname"); exit(1); }/*( * Get pointer to network data structure */: if ( (hostentptr = gethostbyname(hostname)) == NULL) { perror("gethostbyname"); exit(1); }/*$ * Copy hostent data to safe storage */ hostentstruct = *hostentptr;/*4 * Fill in the name & address for the listen socket  */: listenchan_name.sin_family = hostentstruct.h_addrtype;4 listenchan_name.sin_port = htons(poppassd_PORT);K listenchan_name.sin_addr = * ((struct in_addr *) hostentstruct.h_addr);/* * Bind name to socket */I retval = bind (listenchan, &listenchan_name, sizeof listenchan_name); if (retval) { perror("bind"); exit(1); }/*- * Listen on socket for incoming connections  */$ retval = listen (listenchan, 2); if (retval) { perror("listen"); exit(1); }/*$ * Accept connection from the socket */* namelength = sizeof (listenchan_name);? lchan = accept (listenchan, &listenchan_name, &namelength); if (lchan == -1) { perror("accept"); exit (1); } TCPIP = TRUE; return;}#endif /* UCX */*[HALL.TEMP]POPPASSD.MAK;1+,=x./F 4L-*E0123KPWO56be%a7{%a89GFHJ-! Sample make file (poppassd.com or make.com)7! Written by Joel Snyder under contract to SchlumbergerL! Donated to the Public Domain by Schlumberger (David Sims 'dpsims@slb.com')=! Please give credit in any modifications or re-distributions! *Not* for re-sale $ cc poppassd&$ link poppassd,sys$input:/opt/notrace( multinet:multinet_socket_library/share sys$share:vaxcrtl/share*[HALL.TEMP]POPPASSD.TXT;1+,x./F 4O 6-*E0123KPWO56׌%a7r4%a89GFHJN******************************************************************************)System Manager's Notes: poppassd v2.1beta9*** Written by Joel Snyder under contract to SchlumbergerO*** Donated to the Public Domain by Schlumberger (David Sims 'dpsims@slb.com')?*** Please give credit on any modifications or re-distributions*** *Not* for re-saleInstallation Instructions=========================@0- READ THROUGH THE SOURCE TO MAKE SURE THAT THIS DOES WHAT YOU  WANT IT TO DO ! ! !F1- Compile and link it properly. To do that, create a .com file which contains the following:+$ cc poppassd (if you have DEC C, cc/vaxc)&$ link poppassd,sys$input:/opt/notrace( MULTINET:MULTINET_SOCKET_LIBRARY/SHARE SYS$SHARE:VAXCRTL/SHARE42- Put it somewhere. I suggest you put this in yourD MULTINET_COMMON_ROOT:[MULTINET] directories, unless you have some; place else where you keep images like this. To do that:3$ copy poppassd.exe multinet_common_root:[multinet]C3- make Multinet know about it. To do that (assuming you stuck the" file in multinet:poppassd.exe):$ multinet config/serverSERVER-CONFIG>add poppassd7[Adding new configuration entry for service "poppassd"]Protocol: [TCP]TCP Port number: 106%Program to run: MULTINET:poppassd.EXE)[Added service poppassd to configuration]"[Selected service is now poppassd]SERVER-CONFIG>show/fullService "poppassd":3 TCP socket (AF_INET,SOCK_STREAM), Port 106& Socket Options = SO_KEEPALIVE INIT() = TCP_Init LISTEN() = TCP_Listen$ CONNECTED() = TCP_Connected SERVICE() = Run_Program* Program = "MULTINET:poppassd.EXE"SERVER-CONFIG>restartThings you can customize========================CPOP Passwd's behavior can be changed using a variety of system-wideClogical names. The poppassd_LOG_FILE logical name must be defined.=It is currently defined as 'poppassd.log'. Or you must defineKpoppassd_DONT_LOG so that poppassd won't write log files (not recommended).Apoppassd_LOG_FILE This should be defined to point to the location> where poppassd will log everything that happens. By default,< (assuming that you have followed the other instructions and3 recommendations) this code will write the log as: - MULTINET_COMMON_ROOT:[MULTINET]poppassd.log.Apoppassd_DONT_LOG Normally, poppassd logs everything, both errorsC and successes, to a log file. This is usually a pretty good idea.< However, if you do not want poppassd to leave any traces ofC what it has done (including attempted breakins!), then define this( logical name and it will do no logging.Apoppassd_DEBUG You normally would have no reason to define this.; However, if you do, then poppassd will babble all sorts ofC interesting debugging information. Defining this logical does NOT= introduce any security problems; all it does is increase the@ amount of logging to the screen which poppassd will do. If youA define this logical name, then it is likely that Eudora will not be able to talk to poppassd.Apoppassd_ANAL_MODE Normally, poppassd is pretty chatty with users@ about why it was unable to change their password. It will tell> them if a particular username is valid, if they have given an? incorrect password, or if there is a syntax error. Some sites@ may not like the idea of this much information being given out.8 If you define poppassd_ANAL_MODE, then poppassd is very< tight-lipped about the error messages which it gives to the5 client. This does not affect the log files, though.Gpoppassd_IGNORE_LENGTH Normally, poppassd pays attention to the minimumA length of password field in each user's UAF entry. If, for some? very strange reason, you do NOT want poppassd to do this, then9 define this logical name. This is strongly discouraged!?poppassd_IGNORE_CAPTIVE Normally, poppassd will not allow users= who have the CAPTIVE flag in their UAF entry to change their< password. If you would like to allow these users to change0 their passwords, then define this logical name.?poppassd_IGNORE_DISUSER Normally, poppassd will not allow users= who have the DISUSER flag in their UAF entry to change their< password. If you would like to allow these users to changeB their passwords, then define this logical name. This is strongly discouraged!?poppassd_IGNORE_GENPWD Normally, poppassd will not allow users< who have the GENPWD flag in their UAF entry to change their< password. If you would like to allow these users t