head 1.65; access; symbols; locks; strict; comment @ * @; 1.65 date 94.03.21.13.21.31; author paul; state Exp; branches; next 1.64; 1.64 date 94.03.13.20.17.59; author paul; state Exp; branches; next 1.63; 1.63 date 94.03.13.20.11.07; author paul; state Exp; branches; next 1.62; 1.62 date 94.03.12.00.24.45; author paul; state Exp; branches; next 1.61; 1.61 date 94.03.10.23.41.37; author paul; state Exp; branches; next 1.60; 1.60 date 94.03.06.20.47.29; author paul; state Exp; branches; next 1.59; 1.59 date 94.02.24.15.15.40; author paul; state Exp; branches; next 1.58; 1.58 date 94.01.31.21.00.32; author paul; state Exp; branches; next 1.57; 1.57 date 93.12.23.09.56.04; author paul; state Exp; branches; next 1.56; 1.56 date 93.12.19.20.45.42; author paul; state Exp; branches; next 1.55; 1.55 date 93.11.24.22.38.33; author paul; state Exp; branches; next 1.54; 1.54 date 93.11.23.16.27.57; author paul; state Exp; branches; next 1.53; 1.53 date 93.08.04.13.26.00; author paul; state Exp; branches; next 1.52; 1.52 date 93.08.04.12.59.04; author paul; state Exp; branches; next 1.51; 1.51 date 93.07.24.15.53.48; author paul; state Exp; branches; next 1.50; 1.50 date 93.06.16.22.53.41; author paul; state Exp; branches; next 1.49; 1.49 date 93.04.16.02.13.07; author paul; state Exp; branches; next 1.48; 1.48 date 93.04.06.16.53.10; author paul; state Exp; branches; next 1.47; 1.47 date 93.04.05.21.30.18; author paul; state Exp; branches; next 1.46; 1.46 date 93.04.04.04.46.51; author paul; state Exp; branches; next 1.45; 1.45 date 93.04.03.23.53.14; author paul; state Exp; branches; next 1.44; 1.44 date 93.04.02.22.09.16; author paul; state Exp; branches; next 1.43; 1.43 date 93.04.01.20.41.54; author paul; state Exp; branches; next 1.42; 1.42 date 93.03.02.20.49.18; author paul; state Exp; branches; next 1.41; 1.41 date 93.02.26.20.35.36; author paul; state Exp; branches; next 1.40; 1.40 date 93.02.19.22.36.06; author paul; state Exp; branches; next 1.39; 1.39 date 93.02.15.17.23.41; author paul; state Exp; branches; next 1.38; 1.38 date 93.02.14.19.59.43; author paul; state Exp; branches; next 1.37; 1.37 date 92.12.16.23.27.41; author paul; state Exp; branches; next 1.36; 1.36 date 92.12.12.19.07.31; author paul; state Exp; branches; next 1.35; 1.35 date 92.07.29.04.41.04; author paul; state Exp; branches; next 1.34; 1.34 date 92.07.29.03.37.36; author paul; state Exp; branches; next 1.33; 1.33 date 92.07.28.05.06.05; author paul; state Exp; branches; next 1.32; 1.32 date 92.07.27.03.11.26; author paul; state Exp; branches; next 1.31; 1.31 date 92.07.27.01.50.51; author paul; state Exp; branches; next 1.30; 1.30 date 92.07.27.01.45.51; author paul; state Exp; branches; next 1.29; 1.29 date 90.12.18.08.41.17; author dorner; state Exp; branches; next 1.28; 1.28 date 90.05.16.09.18.17; author dorner; state Exp; branches; next 1.27; 1.27 date 89.10.18.07.52.11; author dorner; state Exp; branches; next 1.26; 1.26 date 89.07.19.10.18.37; author dorner; state Exp; branches; next 1.25; 1.25 date 89.07.05.20.16.49; author dorner; state Exp; branches; next 1.24; 1.24 date 89.05.08.22.43.42; author dorner; state Exp; branches; next 1.23; 1.23 date 89.03.20.15.14.35; author dorner; state Exp; branches; next 1.22; 1.22 date 88.12.02.14.45.07; author dorner; state Exp; branches; next 1.21; 1.21 date 88.11.15.13.35.11; author dorner; state Exp; branches; next 1.20; 1.20 date 88.07.27.13.25.35; author dorner; state Exp; branches; next 1.19; 1.19 date 88.07.08.14.00.52; author dorner; state Exp; branches; next 1.18; 1.18 date 88.07.06.20.48.00; author dorner; state Exp; branches; next 1.17; 1.17 date 88.04.19.08.12.15; author dorner; state Exp; branches; next 1.16; 1.16 date 88.03.24.10.53.42; author dorner; state Exp; branches; next 1.15; 1.15 date 88.03.24.10.51.29; author dorner; state Exp; branches; next 1.14; 1.14 date 88.03.23.09.17.46; author dorner; state Exp; branches; next 1.13; 1.13 date 88.03.18.10.31.03; author dorner; state Exp; branches; next 1.12; 1.12 date 88.03.04.09.45.08; author dorner; state Exp; branches; next 1.11; 1.11 date 88.03.02.11.16.13; author dorner; state Exp; branches; next 1.10; 1.10 date 88.02.18.15.02.05; author dorner; state Exp; branches; next 1.9; 1.9 date 88.02.17.08.30.38; author dorner; state Exp; branches; next 1.8; 1.8 date 88.02.16.16.01.16; author dorner; state Exp; branches; next 1.7; 1.7 date 88.02.15.14.03.06; author dorner; state Exp; branches; next 1.6; 1.6 date 88.02.10.13.14.48; author dorner; state Exp; branches; next 1.5; 1.5 date 87.12.12.11.28.23; author dorner; state Exp; branches; next 1.4; 1.4 date 87.12.11.12.12.38; author dorner; state Exp; branches; next 1.3; 1.3 date 87.12.10.16.22.23; author dorner; state Exp; branches; next 1.2; 1.2 date 87.12.10.10.35.00; author dorner; state Exp; branches; next 1.1; 1.1 date 87.12.09.13.36.36; author dorner; state Exp; branches; next ; desc @@ 1.65 log @Added function declaration in case of strstr(). @ text @/* * Copyright (c) 1985 Corporation for Research and Educational Networking * Copyright (c) 1988 University of Illinois Board of Trustees, Steven * Dorner, and Paul Pomes * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Corporation for * Research and Educational Networking (CREN), the University of * Illinois at Urbana, and their contributors. * 4. Neither the name of CREN, the University nor the names of their * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE TRUSTEES AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE TRUSTEES OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static char RcsId[] = "@@(#)$Id: commands.c,v 1.64 1994/03/13 20:17:59 paul Exp paul $"; #endif #include "protos.h" #ifdef __STDC__ #include #else #include #endif #include #include #ifdef KERBEROS #include #include #include #include #include #endif /* KERBEROS */ static ARG *s_args = NULL; static void DoKLogin __P((ARG *)); static void DoAnswer __P((ARG *)); static char *RandomString __P((int)); static int UserMatch __P((char *)); static void DoDelete __P((ARG *)); static void DoFields __P((ARG *)); static void DoId __P((ARG *)); static void DoInfo __P((ARG *)); static void DoLogin __P((ARG *)); static void DoLogout __P((ARG *)); static void DoStatus __P((ARG *)); static void DumpOutput(); static void ListAllFields(); static void ListField __P((FDESC *)); static void NotImplemented __P((ARG *)); static int OkByEmail __P((QDIR, char *)); static int OkFields __P((ARG *)); static int OpenTempOut(); static void PrintCommand __P((int, ARG *)); static void SleepTil __P((long)); #ifdef NO_STRSTR char *strstr __P((char *, char *)); #endif extern FILE *Input; /* qi.c */ extern FILE *Output; /* qi.c */ extern int InputType; /* qi.c */ extern char Foreign[80]; /* qi.c */ extern char CommandText[]; /* language.l */ extern char *CommandSpot; /* language.l */ extern int Daemon; /* qi.c */ extern int Quiet; /* qi.c */ extern int LocalUser; /* qi.c */ extern char *DBState; /* qi.c */ extern char Revision[]; /* version.c */ #ifdef EMAIL_AUTH extern struct hostent TrustHp; /* qi.c */ #endif FILE *TempOutput = NULL; static char *TFile = NULL; int DiscardIt; void (*CommandTable[]) __P((ARG *)) = { DoQuery, DoChange, DoLogin, DoAnswer, DoLogout, DoFields, DoAdd, DoDelete, DoSet, DoQuit, DoStatus, DoId, DoHelp, DoAnswer, DoInfo, DoAnswer, DoKLogin, (void (*) __P((ARG *))) 0 }; QDIR User = NULL; /* the currently logged in user */ int AmHero = 0; /* is currently logged in user the Hero? */ int AmOpr = 0; /* is currently logged in user the Operator? */ char *UserAlias = NULL; /* the alias of the currently logged in user */ int UserEnt = 0; /* entry number of current user */ char *ClaimUser = NULL; /* the identity the user has claimed, but not * yet verified */ char *Challenge = NULL; /* challenge string */ int State = S_IDLE; /* * Add a value to an argument list */ void AddValue(value, ttype) char *value; int ttype; { static ARG *LastArg = NULL; if (!s_args) { LastArg = s_args = FreshArg(); LastArg->aFirst = strdup(value); LastArg->aType = ttype; } else { if (LastArg->aType == VALUE && ttype & EQUAL) LastArg->aType |= ttype; else if (LastArg->aType & EQUAL && !(LastArg->aType & VALUE2)) { LastArg->aType |= VALUE2; LastArg->aSecond = strdup(value); } else { LastArg->aNext = FreshArg(); LastArg = LastArg->aNext; LastArg->aType = ttype; LastArg->aFirst = strdup(value); } } } /* * Complain about extraneous junk */ void Unknown(junk) char *junk; { fprintf(Output, "%d:%s:%s\n", LR_NOCMD, junk, "Command not recognized."); } /* * Execute a command */ void DoCommand(cmd) int cmd; { #define MAX_SYSLOG 100 char c; int which = cmd == C_CLEAR ? 6 : MAX_SYSLOG; c = CommandText[which]; CommandText[which] = '\0'; *CommandSpot = '\0'; if (*CommandText && strstr(CommandText, "password=") == NULL) IssueMessage(LOG_INFO, "%s", CommandText); CommandText[which] = c; if (!Quiet && (InputType == IT_FILE || InputType == IT_PIPE || OP_VALUE(ECHO_OP))) PrintCommand(cmd, s_args); /* echo the cmd */ if (Daemon && GetState()) { fprintf(Output, "555:Database shut off (%s).\n", DBState); exit(0); } if (TempOutput == NULL && !OpenTempOut()) { fprintf(Output, "%d:couldn't open temp file.\n", LR_INTERNAL); IssueMessage(LOG_INFO, "Couldn't open temp file.\n"); goto done; } if (State == S_E_PENDING) { if (DiscardIt || cmd != C_ANSWER && cmd != C_CLEAR && cmd != C_EMAIL) { DoReply(-LR_NOANSWER, "Expecting answer, clear, or email; login discarded."); State = S_IDLE; free(ClaimUser); ClaimUser = NULL; free(Challenge); Challenge = NULL; } } if (DiscardIt) DoReply(LR_SYNTAX, "Command not understood."); else { /* (*CommandTable[cmd - 1]) (s_args); */ void (*cmdP) __P((ARG *)) = *CommandTable[cmd - 1]; if (cmdP != NULL) (*cmdP) (s_args); else DoReply(LR_SYNTAX, "Command not understood."); } DumpOutput(); done: FreeArgs(s_args); s_args = NULL; DiscardIt = 0; } /* * Free the argument list */ void FreeArgs(arg) ARG *arg; { ARG *narg; if (arg) for (narg = arg->aNext; arg; arg = narg) { narg = arg->aNext; if (arg->aFirst) free(arg->aFirst); if (arg->aSecond) free(arg->aSecond); free((char *) arg); arg = NULL; } } /* * create a fresh argument structure */ ARG * FreshArg() { ARG *arg; arg = (ARG *)malloc(sizeof(ARG)); memset((void *) arg, (char)0, sizeof (ARG)); return (arg); } /* * status--give the database status */ /*ARGSUSED*/ static void DoStatus(arg) ARG *arg; { char banner[MAXPATHLEN], vstr[MAXSTR]; FILE *bfp; (void)sprintf(banner, "%s.bnr", Database); if (bfp = fopen(banner, "r")) { (void)sprintf(vstr, "Qi server %s", Revision); DoReply(LR_PROGRESS, vstr); while (fgets(banner, sizeof (banner) - 1, bfp)) { char *nl = strchr(banner, '\n'); if (nl) *nl = '\0'; DoReply(LR_PROGRESS, banner); } (void) fclose(bfp); } if (ReadOnly) DoReply(LR_RONLY, "Database ready, read only (%s).", DBState); else DoReply(LR_OK, "Database ready."); } /* * id--this command is a no-op; the client issues it only to put * the name of the calling user into the nameserver's logfiles */ /*ARGSUSED*/ static void DoId(arg) ARG *arg; { DoReply(LR_OK, "Thanks."); } /* * quit */ /*ARGSUSED*/ void DoQuit(arg) ARG *arg; { fprintf(Output, "%d:%s\n", LR_OK, "Bye!"); fflush(Output); IssueMessage(LOG_INFO, "Done 0"); closelog(); exit(0); } /* * info */ /*ARGSUSED*/ static void DoInfo(arg) ARG *arg; { short n = 0; #ifdef MAILDOMAIN DoReply(-LR_OK, "%d:maildomain:%s", ++n, MAILDOMAIN); #endif DoReply(-LR_OK, "%d:mailfield:%s", ++n, MAILFIELD); DoReply(-LR_OK, "%d:administrator:%s", ++n, ADMIN); DoReply(-LR_OK, "%d:passwords:%s", ++n, PASSW); DoReply(-LR_OK, "%d:mailbox:%s", ++n, MAILBOX); #ifdef CHARSET DoReply(-LR_OK, "%d:charset:%s", ++n, CHARSET); #endif DoReply(LR_OK, "Ok."); } /* * Not implemented */ static void NotImplemented(arg) ARG *arg; { DoReply(500, "%s:command not implemented.", arg->aFirst); } /* * make a reply to a command */ /*VARARGS2*/ void #ifdef __STDC__ DoReply(int code, char *fmt,...) #else /* !__STDC__ */ DoReply(code, fmt, va_alist) int code; char *fmt; va_dcl #endif /* __STDC__ */ { char scratchFormat[256]; va_list args; (void) sprintf(scratchFormat, "%d:%s\n", code, fmt); #ifdef __STDC__ va_start(args, fmt); #else /* !__STDC__ */ va_start(args); #endif /* __STDC__ */ if (TempOutput == NULL && !OpenTempOut()) { fprintf(Output, "%d:couldn't open temp file.\n", LR_INTERNAL); IssueMessage(LOG_INFO, "Couldn't open temp file.\n"); return; } vfprintf(TempOutput, scratchFormat, args); va_end(args); { char buf[4096]; #ifdef __STDC__ va_start(args, fmt); #else /* !__STDC__ */ va_start(args); #endif /* __STDC__ */ vsprintf(buf, scratchFormat, args); va_end(args); /* IssueMessage(LOG_DEBUG, "%s", buf); */ } } /* * identify user, using Kerberos authentication. */ #ifndef KERBEROS static void DoKLogin(arg) ARG *arg; { DoReply(LR_SYNTAX, "%s:Kerberos login not available.", arg->aFirst); } #else static void DoKLogin(arg) ARG *arg; { char *me; me = arg->aFirst; if (arg->aNext) DoReply(LR_SYNTAX, "%s:extra arguments.", me); else { struct sockaddr_in peername, myname; int namelen = sizeof (peername); int status; long authopts; AUTH_DAT auth_data; KTEXT_ST clt_ticket; Key_schedule sched; char instance[INST_SZ]; char version[9]; #ifndef KRBSRVTAB #define KRBSRVTAB "" /* use the kerberos default (/etc/srvtab) */ #endif #ifndef KRBHERO #define KRBHERO "phhero" /* use the default instance */ #endif char *srvtab = KRBSRVTAB; char *heroinst = KRBHERO; fprintf(Output, "%d:Login started; send kerberos mutual authenticator.\n", LR_LOGIN); fflush(Output); /* * To verify authenticity, we need to know the address of the * client. */ if (getpeername(0, (struct sockaddr *) &peername, &namelen) < 0) { IssueMessage(LOG_ERR, "getpeername: %m"); DoReply(LR_INTERNAL, "getpeername: %m"); return; } /* for mutual authentication, we need to know our address */ namelen = sizeof (myname); if (getsockname(0, (struct sockaddr *) &myname, &namelen) < 0) { IssueMessage(LOG_ERR, "getsockname: %m"); DoReply(LR_INTERNAL, "getsockname: %m"); return; } /* * Read the authenticator and decode it. Since we don't care * what the instance is, we use "*" so that krb_rd_req * will fill it in from the authenticator. */ (void) strcpy(instance, "*"); /* we want mutual authentication */ authopts = KOPT_DO_MUTUAL; status = krb_recvauth(authopts, 0, &clt_ticket, "ns", instance, &peername, &myname, &auth_data, srvtab, sched, version); if (status != KSUCCESS) { IssueMessage(LOG_INFO, "Login failed: (%d) %s", status, krb_err_txt[status]); DoReply(LR_ERROR, "Login failed: (%d) %s", status, krb_err_txt[status]); } else { char realm[REALM_SZ]; /* Check the version string (8 chars) */ if (strncmp(version, "VERSION9", 8)) { /* * didn't match the expected version. * could do something different, but we just * log an error and continue. */ version[8] = '\0'; /* make null term */ IssueMessage(LOG_ERR, "Version mismatch: '%s' isn't 'VERSION9'", version); } /* Check to make sure it's in our local realm */ krb_get_lrealm(realm, 1); if (strcmp(auth_data.prealm, realm)) { /* if not equal */ DoReply(LR_ERROR, "Login failed."); IssueMessage(LOG_INFO, "login: realm %s not local realm.", auth_data.prealm); return; } /* * Make sure the instance is a reasonable one (null or KRBHERO). * Dissallow other instances, since who knows what level of privilege * a particular instance means at a given site? */ if (*auth_data.pinst && strcmp(auth_data.pinst,KRBHERO)) { /* not null or phhero */ DoReply(LR_ERROR, "Login failed."); IssueMessage(LOG_INFO, "login: %s.%s not accepted.", auth_data.pname,auth_data.pinst); return; } /* * The user has successfully authenticated, so check * for matching alias, log in and send reply. * * kerberos principal == our alias is auth_data.pname * kerberos instance auth_data.pinst says whether it's * a ph hero. */ if (User) FreeDir(&User); #define WAIT_SECS 1 if (!GonnaRead("DoKlogin")) /* Lock routines give their own errors */ ; else { long xtime = time((long *) NULL); AmHero = 0; UserAlias = NULL; User = GetAliasDir(auth_data.pname); Unlock("DoKlogin"); if (!User) { SleepTil(xtime + WAIT_SECS); DoReply(LR_ERROR, "Login failed."); IssueMessage(LOG_INFO, "login: alias %s does not exist.", auth_data.pname); } else { SleepTil(xtime + WAIT_SECS); DoReply(LR_OK, "%s:Hi how are you?", auth_data.pname); LocalUser = 1; AmHero = !strcmp(auth_data.pinst, KRBHERO) && *FINDVALUE(User, F_HERO); UserAlias = FINDVALUE(User, F_ALIAS); UserEnt = CurrentIndex(); IssueMessage(LOG_INFO, "%s logged in.", UserAlias); } } } } } #endif /*KERBEROS*/ /* * identify user */ static void DoLogin(arg) ARG *arg; { char *me; me = arg->aFirst; arg = arg->aNext; /* skip the command name */ if (!arg) DoReply(LR_SYNTAX, "%s:no name given.", me); else if (arg->aType != VALUE) DoReply(LR_SYNTAX, "%s:argument invalid.", me); else if (arg->aNext) DoReply(LR_SYNTAX, "%s:extra arguments.", me); else { Challenge = strdup(RandomString(42)); DoReply(LR_LOGIN, "%s", Challenge); ClaimUser = strdup(arg->aFirst); AmHero = 0; AmOpr = 0; State = S_E_PENDING; if (User) FreeDir(&User); } } /* * handle the answer to a challenge */ #define WAIT_SECS 1 static void DoAnswer(arg) ARG *arg; { char *me, *pass; long xtime; me = arg->aFirst; arg = arg->aNext; if (!ClaimUser) DoReply(LR_SYNTAX, "%s:there is no outstanding login.", me); else if (!arg) DoReply(LR_SYNTAX, "%s:no argument given.", me); else if (arg->aType != VALUE) DoReply(LR_SYNTAX, "%s:invalid argument type.", me); else if (!GonnaRead("DoAnswer")) /* Lock routines give their own errors */ ; else { AmHero = 0; AmOpr = 0; UserAlias = NULL; xtime = time((long *) NULL); if (User = GetAliasDir(ClaimUser)) pass = PasswordOf(User); Unlock("DoAnswer"); if (!User) { SleepTil(xtime + WAIT_SECS); DoReply(LR_ERROR, "Login failed."); IssueMessage(LOG_INFO, "login: alias %s does not exist.", ClaimUser); } else if (((*me == 'a' || *me == 'A') && !UserMatch(arg->aFirst)) || #ifdef EMAIL_AUTH ((*me == 'e' || *me == 'E') && !OkByEmail(User, arg->aFirst)) || #endif #ifndef PRE_ENCRYPT (((*me == 'c' || *me == 'C') && *pass) && strcmp(arg->aFirst, pass)) #else (((*me == 'c' || *me == 'C') && *pass) && strncmp(crypt(arg->aFirst, arg->aFirst), pass, 13)) #endif ) { SleepTil(xtime + WAIT_SECS); if (*me != 'e' && *me != 'E') { DoReply(LR_ERROR, "Login failed."); IssueMessage(LOG_INFO, "Password incorrect for %s.", ClaimUser); } FreeDir(&User); } else { char *tpnt = FINDVALUE(User, F_HERO); SleepTil(xtime + WAIT_SECS); DoReply(LR_OK, "%s:Hi how are you?", ClaimUser); if (*tpnt != '\0') { if (stricmp(tpnt, "opr") == 0 || stricmp(tpnt, "oper") == 0 || stricmp(tpnt, "operator") == 0) AmOpr = 1; else AmHero = 1; } LocalUser = 1; UserAlias = FINDVALUE(User, F_ALIAS); UserEnt = CurrentIndex(); IssueMessage(LOG_INFO, "%s logged in.", UserAlias); } } if (ClaimUser) { free(ClaimUser); ClaimUser = NULL; } if (Challenge) { free(Challenge); Challenge = NULL; } State = S_IDLE; } /* * sleep til a given time */ static void SleepTil(xtime) long xtime; { unsigned span; span = xtime - time((long *) 0); if (0 < span && span < 10000) sleep(span); } /* * return the dir entry of the requested alias */ QDIR GetAliasDir(fname) char *fname; { ARG *Alist; ARG *arg; long *entry; QDIR dirp; arg = Alist = FreshArg(); arg->aType = COMMAND; arg->aFirst = strdup("query"); arg->aNext = FreshArg(); arg = arg->aNext; arg->aType = VALUE | EQUAL | VALUE2; arg->aFirst = strdup("alias"); /* should be alias */ arg->aSecond = strdup(fname); (void) ValidQuery(Alist, C_QUERY); if ((entry = DoLookup(Alist)) != NULL && length(entry) == 1 && next_ent(*entry)) getdata(&dirp); else dirp = NULL; if (entry) free((char *) entry); FreeArgs(Alist); return (dirp); } /* * de-identify the current user */ static void DoLogout(arg) ARG *arg; { if (arg->aNext) DoReply(LR_SYNTAX, "argument given on logout command."); else if (!User) DoReply(LR_ERROR, "Not logged in."); else { FreeDir(&User); AmHero = 0; AmOpr = 0; UserAlias = NULL; UserEnt = 0; DoReply(LR_OK, "Ok."); } } /* * list fields */ static void DoFields(arg) ARG *arg; { if (arg->aNext == NULL) { ListAllFields(); DoReply(LR_OK, "Ok."); } else if (OkFields(arg->aNext)) { for (arg = arg->aNext; arg; arg = arg->aNext) if (arg->aFD) ListField(arg->aFD); DoReply(LR_OK, "Ok."); } else DoReply(LR_SYNTAX, "Invalid field request."); } /* * List a single field */ static void ListField(fd) FDESC *fd; { char scratch[MAX_LEN]; char *cp; (void) sprintf(scratch, "%d:%s:max %d", fd->fdId, fd->fdName, fd->fdMax); cp = scratch + strlen(scratch); if (fd->fdIndexed) cp += strcpc(cp, " Indexed"); if (fd->fdLookup) cp += strcpc(cp, " Lookup"); if (fd->fdPublic) cp += strcpc(cp, " Public"); if (fd->fdLocalPub) cp += strcpc(cp, " LocalPub"); if (fd->fdDefault) cp += strcpc(cp, " Default"); if (fd->fdAlways) cp += strcpc(cp, " Always"); if (fd->fdAny) cp += strcpc(cp, " Any"); if (fd->fdChange) cp += strcpc(cp, " Change"); if (fd->fdSacred) cp += strcpc(cp, " Sacred"); if (fd->fdTurn) cp += strcpc(cp, " Turn"); if (fd->fdEncrypt) cp += strcpc(cp, " Encrypt"); if (fd->fdNoPeople) cp += strcpc(cp, " NoPeople"); *cp = '\0'; DoReply(-LR_OK, scratch); strcpy(scratch, fd->fdHelp); for (cp = strtok(scratch, "\n"); cp; cp = strtok((char *) NULL, "\n")) DoReply(-LR_OK, "%d:%s:%s", fd->fdId, fd->fdName, cp); } /* * list all fields */ static void ListAllFields() { FDESC **fd; for (fd = FieldDescriptors; *fd; fd++) { if ((*fd)->fdLocalPub && !LocalUser) continue; ListField(*fd); } } /* * validate arguments for field names */ static int OkFields(arg) ARG *arg; { int bad = 0; int count = 0; FDESC *fd; for (; arg; arg = arg->aNext) { count++; if (arg->aType != VALUE) { DoReply(-LR_SYNTAX, "argument %d:is not a field name.", count); bad = 1; } else if (!(fd = FindFD(arg->aFirst)) || (!LocalUser && fd->fdLocalPub)) { DoReply(-LR_FIELD, "%s:unknown field.", arg->aFirst); bad = 1; } else arg->aFD = fd; } return (!bad); } /* * delete entries */ static void DoDelete(arg) ARG *arg; { long *entries, *entp; int haveError = 0; int count; int done; QDIR dirp; if (!AmHero && !User) { DoReply(LR_NOTLOG, "Must be logged in to delete."); return; } else if (!UserCanDelete()) { DoReply(LR_ERROR, "You may not delete entries."); IssueMessage(LOG_INFO, "%s is not authorized to delete entries.", UserAlias); return; } if (!ValidQuery(arg, C_DELETE)) { DoReply(LR_SYNTAX, "Delete command not understood."); return; } if (!GonnaWrite("DoDelete")) { /* GonnaWrite will issue an error message */ ; return; } if ((entries = DoLookup(arg)) == NULL) { Unlock("DoDelete"); DoReply(LR_NOMATCH, "No entries matched specifications."); return; } for (count = 1, done = 0, entp = entries; *entp; count++, entp++) { if (!next_ent(*entp)) { DoReply(-LR_TEMP, "Internal error."); haveError = 1; continue; } getdata(&dirp); if (!CanDelete(dirp)) { DoReply(-LR_ERROR, "%d:%s: you may not delete this entry.", count, FINDVALUE(dirp, F_ALIAS)); haveError = 1; IssueMessage(LOG_INFO, "%s may not delete %s.", UserAlias, FINDVALUE(dirp, F_ALIAS)); FreeDir(&dirp); /* XXX */ continue; } /* delete the index entries */ MakeLookup(dirp, *entp, unmake_lookup); FreeDir(&dirp); /* mark it as dead and put it out to pasture */ SetDeleteMark(); set_date(1); store_ent(); done++; } free((char *) entries); Unlock("DoDelete"); if (haveError) DoReply(LR_ERROR, "%d errors, %d successes on delete command.", count - done, done); else DoReply(LR_OK, "%d entries deleted.", done); } /* * open a temp file for output */ static int OpenTempOut() { if (TFile == NULL) { TFile = strdup(TEMPFILE); mktemp(TFile); } if ((TempOutput = fopen(TFile, "w+")) == NULL) { free(TFile); TFile = NULL; return (0); } unlink(TFile); return (1); } /* * Dump a the stuff in TFile to output */ static void DumpOutput() { int c; rewind(TempOutput); /* back to the beginning */ { while ((c = getc(TempOutput)) != EOF) putc(c, Output); } fclose(TempOutput); /* close; already unlinked */ TempOutput = NULL; fflush(Output); } /* * print the current command */ static void PrintCommand(cmd, arg) int cmd; ARG *arg; { fprintf(Output, "%d: %s", LR_ECHO, arg->aFirst); for (arg = arg->aNext; arg; arg = arg->aNext) { putc(' ', Output); if (arg->aType == RETURN) fputs(cmd == C_QUERY ? "return" : "make", Output); else { if (arg->aType & VALUE) fputs(arg->aFirst, Output); #ifdef DO_TILDE if (arg->aType & TILD_E) putc('~', Output); else #endif if (arg->aType & EQUAL) putc('=', Output); if (arg->aType & VALUE2) fputs(arg->aSecond, Output); } } putc('\n', Output); } /* * was the returned string encrypted with the appropriate password? */ static int UserMatch(string) char *string; { char decrypted[MAXSTR]; char *pw = PasswordOf(User); if (!*pw) return (0); crypt_start(pw); (void) decrypt(decrypted, string); return (!strcmp(decrypted, Challenge)); } /* * generate a random string */ static char * RandomString(byteCount) int byteCount; { static char string[MAXSTR]; char *cp; static int seeded = 0; if (!seeded) { seeded = 1; srand((int) time((long *) NULL) ^ getpid()); } for (cp = string; byteCount; cp++, byteCount--) *cp = (rand() & 0x3f) + 0x21; return (string); } /* * extract the password from a dir */ char * PasswordOf(User) QDIR User; { int len; char *password; /* find the user's password */ if (!*(password = FINDVALUE(User, F_PASSWORD))) { #ifdef ID_FALLBACK if (*(password = FINDVALUE(User, F_UNIVID))) { len = strlen(password); if (len > 8) password += len - 8; } else #endif password = ""; } return (password); } #ifdef EMAIL_AUTH /* * figure out if a user is ok by his email address */ static int OkByEmail(User, username) QDIR User; char *username; { char buf[256]; char *email = FINDVALUE(User, F_EMAIL); char *new, *spnt, *epnt; int result; /* * Fix up email field by omitting leading whitespace and * terminating it at the first white space. */ new = spnt = strdup(email); while (isspace(*spnt)) spnt++; epnt = spnt; while (*epnt && !isspace(*epnt)) epnt++; *epnt = '\0'; if (!TrustHp.h_name || !*spnt) result = 1; else { (void) sprintf(buf, "%s@@%s", username, TrustHp.h_name); result = stricmp(spnt, buf); } free(new); if (result) DoReply(LR_NOEMAIL, "You can't login that way."); return (!result); } #endif /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms are permitted * provided that: (1) source distributions retain this entire copyright * notice and comment, and (2) distributions including binaries display * the following acknowledgement: ``This product includes software * developed by the University of California, Berkeley and its contributors'' * in the documentation or other materials provided with the distribution * and in all advertising materials mentioning features or use of this * software. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@@(#)strstr.c 5.1 (Berkeley) 5/15/90"; #endif /* LIBC_SCCS and not lint */ #ifdef NO_STRSTR /* * Find the first occurrence of find in s. */ char * strstr(s, find) register char *s, *find; { register char c, sc; register int len; if ((c = *find++) != 0) { len = strlen(find); do { do { if ((sc = *s++) == 0) return ((char *) 0); } while (sc != c); } while (strncmp(s, find, len) != 0); s--; } return ((char *)s); } #endif @ 1.64 log @*** empty log message *** @ text @d38 1 a38 1 static char RcsId[] = "@@(#)$Id: commands.c,v 1.63 1994/03/13 20:11:07 paul Exp paul $"; d81 3 @ 1.63 log @Added strdup() source. @ text @d38 1 a38 1 static char RcsId[] = "@@(#)$Id: commands.c,v 1.62 1994/03/12 00:24:45 paul Exp paul $"; d193 1 a193 1 if (*CommandText && !strstr(CommandText, "password=")) @ 1.62 log @Added new copyright statement. @ text @d38 1 a38 1 static char RcsId[] = "@@(#)$Id$"; d1132 52 @ 1.61 log @Don't log password changes. Fixed a *nasty* little bug that caused malloc() arena corruption and unexpected "oops: lost connection to server" segmentation faults. @ text @a0 2 #include "protos.h" d2 33 a34 5 * This software is Copyright (C) 1988 by Steven Dorner and the * University of Illinois Board of Trustees. No warranties of any * kind are expressed or implied. No support will be provided. * This software may not be redistributed for commercial purposes. * You may direct questions to nameserv@@uiuc.edu d36 6 @ 1.60 log @On the road to finding a malloc bug @ text @d161 2 a162 1 IssueMessage(LOG_INFO, "%s", CommandText); d1084 1 a1084 1 while (!isspace(*epnt)) @ 1.59 log @Implement MAILDOMAIN and CHARSET siteinfo fields. Make fields marked as LocalPub invisible, not just un-searchable, to non-local users. @ text @a27 1 static ARG *LastArg; d67 2 a68 2 FILE *TempOutput = 0; static char *TFile = 0; d93 1 a93 1 QDIR User = 0; /* the currently logged in user */ d96 1 a96 1 char *UserAlias = 0; /* the alias of the currently logged in user */ d99 1 a99 1 char *ClaimUser = 0; /* the identity the user has claimed, but not d101 1 a101 1 char *Challenge = 0; /* challenge string */ d112 2 d184 1 a184 1 ClaimUser = 0; d186 1 a186 1 Challenge = 0; d228 1 d240 1 a240 1 arg = NEW(ARG); d261 1 a261 1 while (fgets(banner, sizeof (banner), bfp)) d266 1 a266 1 *nl = 0; d519 1 a519 1 UserAlias = 0; d600 1 a600 1 UserAlias = 0; d688 1 a688 1 static QDIR dirp; d730 1 a730 1 UserAlias = 0; d793 1 a793 1 *cp = 0; d898 1 d1072 1 a1072 1 char *pnt; d1079 8 a1086 8 email = strcpy(malloc(strlen(email) + 1), email); while (isspace(*email)) email++; pnt = email; while (!isspace(*pnt)) pnt++; *pnt = '\0'; if (!TrustHp.h_name || !*email) d1091 1 a1091 1 result = stricmp(email, buf); d1093 1 @ 1.58 log @*** empty log message *** @ text @d51 4 a54 4 extern FILE *Input; /* mqi.c */ extern FILE *Output; /* mqi.c */ extern int InputType; /* mqi.c */ extern char Foreign[80]; /* mqi.c */ d57 4 a60 3 extern int Daemon; /* mqi.c */ extern int Quiet; /* mqi.c */ extern char *DBState; /* mqi.c */ d312 1 a313 2 #ifndef MAILFIELD #define MAILFIELD "alias" d318 3 a320 2 #ifndef MAILBOX #define MAILBOX "email" a321 1 DoReply(-LR_OK, "%d:mailbox:%s", ++n, MAILBOX); d529 1 d643 1 d806 3 a808 1 for (fd = FieldDescriptors; *fd; fd++) d810 1 d831 1 a831 1 } else if (!(fd = FindFD(arg->aFirst))) @ 1.57 log @Replaced make_str() with strdup(). @ text @d318 4 @ 1.56 log @Fixed typo. @ text @d115 1 a115 1 LastArg->aFirst = make_str(value); d124 1 a124 1 LastArg->aSecond = make_str(value); d130 1 a130 1 LastArg->aFirst = make_str(value); d556 1 a556 1 Challenge = make_str(RandomString(42)); d558 1 a558 1 ClaimUser = make_str(arg->aFirst); d685 1 a685 1 arg->aFirst = make_str("query"); d689 2 a690 2 arg->aFirst = make_str("alias"); /* should be alias */ arg->aSecond = make_str(fname); d918 1 a918 1 TFile = make_str(TEMPFILE); @ 1.55 log @*** empty log message *** @ text @d385 1 a385 1 DoReply(LR_SYNTAX, "%s:Kerberos login not available.", me); @ 1.54 log @Made TrustHp a real hostent instead of a pointer to one. @ text @a29 1 #ifdef KERBEROS a30 1 #else /* !KERBEROS */ a33 2 #endif /* KERBEROS */ a75 3 #ifdef KERBEROS DoKLogin, #else /* !KERBEROS */ a76 1 #endif /* KERBEROS */ a85 5 #ifdef KERBEROS (void (*) __P((ARG *))) 0, DoInfo, (void (*) __P((ARG *))) 0, #else /* !KERBEROS */ d89 1 a89 1 #endif /* KERBEROS */ a98 1 #ifndef KERBEROS a102 1 #endif /* !KERBEROS */ a153 3 #ifdef KERBEROS int which = MAX_SYSLOG; #else /* KERBEROS */ a154 1 #endif /* KERBEROS */ a174 1 #ifndef KERBEROS a186 1 #endif /* !KERBEROS */ d312 4 a315 1 DoReply(-LR_OK, "%d:mailfield:alias", ++n); a376 1 #ifdef KERBEROS d378 1 a378 1 * identify user d380 8 d408 9 d451 2 a452 2 instance, &peername, &myname, &auth_data, "", sched, version); d483 11 d525 1 a525 1 AmHero = !strcmp(auth_data.pinst, "phhero") && d536 1 a536 11 /* * A non-kerberized client has tried to login, which we do not allow. */ static void DoLogin(arg) ARG *arg; { DoReply(LR_SYNTAX, "This is a Kerberized name server; you must use a kerberized client to log in"); } #else /* !KERBEROS */ a654 1 #endif /* !KERBEROS */ d720 4 a983 1 #ifndef KERBEROS a1047 1 #endif /* !KERBEROS */ @ 1.53 log @Comment out debug syslog. @ text @d67 1 a67 1 extern struct hostent *TrustHp; /* qi.c */ d1074 1 a1074 1 if (!TrustHp || !*email) d1078 1 a1078 1 (void) sprintf(buf, "%s@@%s", username, TrustHp->h_name); @ 1.52 log @GonnaWrite(), GonnaRead(), and Unlock() now take a char string arg. @ text @d391 1 a391 1 IssueMessage(LOG_DEBUG, "%s", buf); @ 1.51 log @POSIX changes: bzero() -> memset(), index() -> strchr(). @ text @d497 1 a497 1 if (!GonnaRead()) d505 3 a507 1 if (!(User = GetAliasDir(auth_data.pname))) d588 1 a588 1 else if (!GonnaRead()) d598 1 a654 1 Unlock(); d858 1 a858 1 if (!GonnaWrite()) d865 1 a866 1 Unlock(); d899 1 a899 1 Unlock(); @ 1.50 log @Use temporary variable for password instead of multiple function calls. @ text @d259 1 a259 1 bzero((void *) arg, sizeof (ARG)); d281 1 a281 1 char *nl = index(banner, '\n'); @ 1.49 log @Made Quiet a global so command echoing can be turned off for pipes in commands.c . @ text @d574 1 a574 1 char *me; d594 3 a596 1 if (!(User = GetAliasDir(ClaimUser))) d602 3 d606 2 a607 1 ((*me == 'c' || *me == 'C') && strcmp(arg->aFirst, PasswordOf(User))) d609 2 a610 5 ((*me == 'c' || *me == 'C') && strncmp(crypt(arg->aFirst, arg->aFirst), PasswordOf(User), 13)) #endif #ifdef EMAIL_AUTH || ((*me == 'e' || *me == 'E') && !OkByEmail(User, arg->aFirst)) @ 1.48 log @Guard against NULL CommandTable entries. @ text @d62 1 d180 1 a180 1 if (InputType == IT_FILE || InputType == IT_PIPE || OP_VALUE(ECHO_OP)) @ 1.47 log @Many functions converted to static for better localization and fewer side effects. Modest space savings as well. @ text @d210 9 a218 1 (*CommandTable[cmd - 1]) (s_args); @ 1.46 log @Print server revision level when printing prod.bnr file. @ text @d30 25 d244 1 a244 1 ARG * d258 1 a258 1 void d291 1 a291 1 void d317 1 a317 1 void d333 1 a333 1 void d390 1 a390 1 void d519 1 a519 1 void d530 1 a530 1 void a534 1 char *RandomString(); d561 1 a561 1 void d647 1 a647 1 void d697 1 a697 1 void d715 1 a715 1 void d736 1 a736 1 void d779 1 a779 1 void d791 1 a791 1 int d819 1 a819 1 void d897 1 a897 1 int d919 1 a919 1 void d937 1 a937 1 void d972 1 a972 1 int d989 1 a989 1 char * d1011 1 a1011 1 char * d1039 1 a1039 1 int @ 1.45 log @Kerberos changes from Brown University. @ text @d38 1 d237 1 a237 1 char banner[MAXPATHLEN]; d243 2 @ 1.44 log @Allow login to read-only database but disallow all changes. This allows terminal server users to validate their passwords while the database is marked read-only for updates. @ text @d19 8 d53 3 d57 1 d67 5 d75 1 d85 1 d90 1 d142 3 d146 1 d167 1 d180 1 d358 141 d615 1 d941 1 d1006 1 @ 1.43 log @Added LocalPub changes. @ text @d394 1 a394 4 if (ReadOnly) DoReply(LR_READONLY, "login not allowed to read-only database."); else DoReply(LR_ERROR, "Login failed."); d411 2 a412 7 if (ReadOnly) DoReply(LR_READONLY, "login not allowed to read-only database."); else { DoReply(LR_ERROR, "Login failed."); IssueMessage(LOG_INFO, "Password incorrect for %s.", ClaimUser); } a414 4 } else if (ReadOnly) { DoReply(LR_COULDA_BEEN, "login not allowed to read-only database."); FreeDir(&User); d813 1 a813 1 * extract the password form a dir d871 1 a871 8 { if (ReadOnly) { DoReply(LR_READONLY, "login not allowed to read-only database."); result = 1; } else DoReply(LR_NOEMAIL, "You can't login that way."); } @ 1.42 log @Writing to constant strings is a *bad* thing. @ text @d568 2 @ 1.41 log @Strip leading and trailing whitespace from email field for login purposes. @ text @d866 1 @ 1.40 log @Make sure TempOutput is open() before writing to it. @ text @d851 1 a851 1 ************************************************************************/ d859 1 d862 10 @ 1.39 log @Make email authorization comparison case-insensitive. @ text @d137 1 a137 1 if (!OpenTempOut()) d310 6 d745 1 @ 1.38 log @Now supports the less-than-all-powerful hero. If the hero field contains the string "opr", "oper", or "operator", then the user is allowed nearly unlimited proxy-like priviledges. The exception is that the operator may not change an entry of any user that has a non-empty hero field. Use is for consultants so that they can change passwords and email entries, but not name or id fields. In addition they can't add or delete entries. @ text @d859 1 a859 1 result = strcmp(email, buf); @ 1.37 log @rand/srand are more commone than random/srandom. @ text @d63 1 d350 1 d382 1 d423 2 d427 9 a435 1 AmHero = *FINDVALUE(User, F_HERO); @ 1.36 log @Up-cased all #define's. @ text @d794 1 a794 1 srandom((int) time((long *) NULL) ^ getpid()); d797 1 a797 1 *cp = (random() & 0x3f) + 0x21; @ 1.35 log @Revised #include file list. @ text @d196 1 a196 1 arg = New(ARG); d212 1 a212 2 strcpy(banner, Database); strcat(banner, ".bnr"); d268 1 a268 1 DoReply(-LR_OK, "%d:maildomain:%s", ++n, MailDomain); d270 2 a271 2 DoReply(-LR_OK, "%d:administrator:%s", ++n, Admin); DoReply(-LR_OK, "%d:passwords:%s", ++n, Passw); d422 2 a423 2 AmHero = *FindValue(User, F_HERO); UserAlias = FindValue(User, F_ALIAS); d663 1 a663 1 count, FindValue(dirp, F_ALIAS)); d666 1 a666 1 UserAlias, FindValue(dirp, F_ALIAS)); d698 1 a698 1 TFile = make_str(Tempfile); d813 1 a813 1 if (!*(password = FindValue(User, F_PASSWORD))) d816 1 a816 1 if (*(password = FindValue(User, F_UNIVID))) d838 1 a838 1 char *email = FindValue(User, F_EMAIL); @ 1.34 log @Deleted #include in favor of one in qi.h. @ text @a10 3 #include "conf.h" #include #include a17 4 #include "commands.h" #include "options.h" #include "field.h" #include "qi.h" @ 1.33 log @Random fixes. @ text @a12 1 #include @ 1.32 log @*** empty log message *** @ text @d15 1 d17 3 d48 1 a48 1 void (*CommandTable[])(ARG *) = d66 1 a66 1 (void (*)(ARG *)) 0 d302 2 a303 2 DoReply(code, fmt, va_list) int code d625 2 a626 1 DoDelete(ARG * arg) d703 1 a703 1 OpenTempOut(void) a704 3 char *make_str(); char *mktemp(); d725 1 a725 1 DumpOutput(void) @ 1.31 log @moved matching paren out if #ifdef wrapper. @ text @d3 7 a9 7 /********************************************************************* * This software is Copyright (C) 1988 by Steven Dorner and the * University of Illinois Board of Trustees. No warranties of any * kind are expressed or implied. No support will be provided. * This software may not be redistributed for commercial purposes. * You may direct questions to dorner@@garcon.cso.uiuc.edu **********************************************************************/ d23 2 a24 2 static Arg *TheArgs = NULL; static Arg *LastArg; d26 9 a34 8 extern FILE *Input; /* mqi.c */ extern FILE *Output; /* mqi.c */ extern int InputType; /* mqi.c */ extern char Foreign[80]; /* mqi.c */ extern char CommandText[]; /* language.l */ extern char *CommandSpot; /* language.l */ extern int Daemon; /* mqi.c */ extern char *DBState; /* mqi.c */ d36 2 a37 1 extern struct hostent *TrustHostEnt; /* qi.c */ d40 1 a40 1 FILE *TempOutput = 0; d43 2 a44 2 int DiscardIt; void (*CommandTable[]) (Arg *theArg) = d46 17 a62 17 DoQuery, DoChange, DoLogin, DoAnswer, DoLogout, DoFields, DoAdd, DoDelete, DoSet, DoQuit, DoStatus, DoId, DoHelp, DoAnswer, DoInfo, DoAnswer, (void (*)(Arg *theArg))0 d65 57 a121 52 Dir User = 0; /* the currently logged in user */ int AmHero = 0; /* is currently logged in user the Hero? */ char *UserAlias = 0; /* the alias of the currently logged in user */ int UserEnt = 0; /* entry number of current user */ char *ClaimUser = 0; /* the identity the user has claimed, but not * yet verified */ char *Challenge = 0; /* challenge string */ int State = S_IDLE; /*********************************************************************** * Add a value to an argument list ***********************************************************************/ void AddValue(char *theValue,int theType) { if (!TheArgs) { LastArg = TheArgs = FreshArg(); LastArg->aFirst = make_str(theValue); LastArg->aType = theType; } else { if (LastArg->aType == VALUE && theType & EQUAL) LastArg->aType |= theType; else if (LastArg->aType&EQUAL && !(LastArg->aType&VALUE2)) { LastArg->aType |= VALUE2; LastArg->aSecond = make_str(theValue); } else { LastArg->aNext = FreshArg(); LastArg = LastArg->aNext; LastArg->aType = theType; LastArg->aFirst = make_str(theValue); } } } /*********************************************************************** * Complain about extraneous junk ***********************************************************************/ void Unknown(char *theJunk) { fprintf(Output, "%d:%s:%s\n", LR_NOCMD, theJunk, "Command not recognized."); } /*********************************************************************** * Execute a command ***********************************************************************/ void DoCommand(int theCommand) d124 84 a207 84 char c; int which = theCommand == C_CLEAR ? 6 : MAX_SYSLOG; c = CommandText[which]; CommandText[which] = '\0'; *CommandSpot = '\0'; IssueMessage(LOG_INFO, "%s", CommandText); CommandText[which] = c; if (InputType == IT_FILE || InputType == IT_PIPE || OP_VALUE(ECHO_OP)) PrintCommand(theCommand, TheArgs); /* echo the cmd */ if (Daemon && GetState()) { fprintf(Output, "555:Database shut off (%s).\n", DBState); exit(0); } if (!OpenTempOut()) { fprintf(Output, "%d:couldn't open temp file.\n", LR_INTERNAL); IssueMessage(LOG_INFO, "Couldn't open temp file.\n"); goto done; } if (State == S_E_PENDING) { if (DiscardIt || theCommand != C_ANSWER && theCommand != C_CLEAR && theCommand != C_EMAIL) { DoReply(-LR_NOANSWER, "Expecting answer, clear, or email; login discarded."); State = S_IDLE; free(ClaimUser); ClaimUser = 0; free(Challenge); Challenge = 0; } } if (DiscardIt) DoReply(LR_SYNTAX, "Command not understood."); else (*CommandTable[theCommand - 1]) (TheArgs); DumpOutput(); done: FreeArgs(TheArgs); TheArgs = NULL; DiscardIt = 0; } /*********************************************************************** * Free the argument list ***********************************************************************/ void FreeArgs(Arg *theArg) { Arg *theNext; if (theArg) for (theNext=theArg->aNext; theArg; theArg=theNext) { theNext = theArg->aNext; if (theArg->aFirst) free(theArg->aFirst); if (theArg->aSecond) free(theArg->aSecond); free((char *)theArg); } } /*********************************************************************** * create a fresh argument structure ***********************************************************************/ Arg *FreshArg() { Arg *theArg; theArg = New(Arg); bzero((void*)theArg,sizeof(Arg)); return (theArg); } /*********************************************************************** * status--give the database status ***********************************************************************/ d209 31 a239 26 void DoStatus(Arg *theArg) { char banner[MAXPATHLEN]; FILE *bfp; strcpy(banner,Database); strcat(banner,".bnr"); if (bfp=fopen(banner,"r")) { while (fgets(banner,sizeof(banner),bfp)) { char *nl = index(banner,'\n'); if (nl) *nl = 0; DoReply(LR_PROGRESS,banner); } fclose(bfp); } if (ReadOnly) DoReply(LR_RONLY,"Database ready, read only (%s).", DBState); else DoReply(LR_OK,"Database ready."); } /*********************************************************************** * id--this command is a no-op; the client issues it only to put * the name of the calling user into the nameserver's logfiles ***********************************************************************/ d241 3 a243 1 void DoId(Arg *theArg) d245 1 a245 1 DoReply(LR_OK,"Thanks."); d248 3 a250 3 /*********************************************************************** * quit ***********************************************************************/ d252 9 a260 7 void DoQuit(Arg *theArg) { fprintf(Output,"%d:%s\n",LR_OK, "Bye!"); fflush(Output); IssueMessage(LOG_INFO,"Done 0"); closelog(); exit(0); d263 3 a265 3 /*********************************************************************** * info ***********************************************************************/ d267 3 a269 1 void DoInfo(Arg *theArg) d271 7 a277 6 short n=0; DoReply(-LR_OK,"%d:maildomain:%s",++n,MailDomain); DoReply(-LR_OK,"%d:mailfield:alias",++n); DoReply(-LR_OK,"%d:administrator:%s",++n,Admin); DoReply(-LR_OK,"%d:passwords:%s",++n,Passw); DoReply(LR_OK,"Ok."); d280 6 a285 4 /*********************************************************************** * Not implemented ***********************************************************************/ void NotImplemented(Arg *theArg) d287 1 a287 1 DoReply(500, "%s:command not implemented.", theArg->aFirst); d290 3 a292 3 /*********************************************************************** * make a reply to a command ***********************************************************************/ d294 24 a317 61 void DoReply(int theCode,char *theFormat,...) { char scratchFormat[256]; va_list args; sprintf(scratchFormat, "%d:%s\n", theCode, theFormat); va_start(args,theFormat); #ifdef NO_VFPRINTF _doprnt(scratchFormat,args,TempOutput); #else vfprintf(TempOutput,scratchFormat, args); #endif va_end(args); { char buf[4096]; va_start(args,theFormat); vsprintf(buf,scratchFormat,args); va_end(args); IssueMessage(LOG_DEBUG,"%s",buf); } } /*********************************************************************** * identify user ***********************************************************************/ void DoLogin(Arg *theArg) { char *me; char *RandomString(); me = theArg->aFirst; theArg = theArg->aNext; /* skip the command name */ if (!theArg) DoReply(LR_SYNTAX, "%s:no name given.", me); else if (theArg->aType != VALUE) DoReply(LR_SYNTAX, "%s:argument invalid.", me); else if (theArg->aNext) DoReply(LR_SYNTAX, "%s:extra arguments.", me); else { Challenge = make_str(RandomString(42)); DoReply(LR_LOGIN, "%s", Challenge); ClaimUser = make_str(theArg->aFirst); AmHero = 0; State = S_E_PENDING; if (User) FreeDir(&User); } } /*********************************************************************** * handle the answer to a challenge ***********************************************************************/ #define WAIT_SECS 1 void DoAnswer(Arg *theArg) { char *me; long time(), theTime; d319 40 a358 2 me = theArg->aFirst; theArg = theArg->aNext; d360 36 a395 23 if (!ClaimUser) DoReply(LR_SYNTAX, "%s:there is no outstanding login.", me); else if (!theArg) DoReply(LR_SYNTAX, "%s:no argument given.", me); else if (theArg->aType != VALUE) DoReply(LR_SYNTAX, "%s:invalid argument type.", me); else if (!GonnaRead()) /* Lock routines give their own errors */ ; else { AmHero = 0; UserAlias = 0; theTime = time((long *)NULL); if (!(User = GetAliasDir(ClaimUser))) { SleepTil(theTime + WAIT_SECS); if (ReadOnly) DoReply(LR_READONLY, "login not allowed to read-only database."); else DoReply(LR_ERROR, "Login failed."); IssueMessage(LOG_INFO, "login: alias %s does not exist.", ClaimUser); } else if (((*me=='a' || *me=='A') && !UserMatch(theArg->aFirst)) || d397 1 a397 1 ((*me=='c'||*me=='C') && strcmp(theArg->aFirst,PasswordOf(User))) d399 2 a400 2 ((*me=='c'||*me=='C') && strncmp(crypt(theArg->aFirst,theArg->aFirst),PasswordOf(User),13)) d403 1 a403 1 || ((*me=='e'||*me=='E')&&!OkByEmail(User,theArg->aFirst)) d405 285 a689 7 ) { SleepTil(theTime + WAIT_SECS); if (*me!='e'&&*me!='E') { if (ReadOnly) DoReply(LR_READONLY, "login not allowed to read-only database."); d691 37 d729 27 a755 341 DoReply(LR_ERROR, "Login failed."); IssueMessage(LOG_INFO, "Password incorrect for %s.", ClaimUser); } } FreeDir(&User); } else if (ReadOnly) { DoReply(LR_COULDA_BEEN, "login not allowed to read-only database."); FreeDir(&User); } else { SleepTil(theTime + WAIT_SECS); DoReply(LR_OK, "%s:Hi how are you?", ClaimUser); AmHero = *FindValue(User, F_HERO); UserAlias = FindValue(User, F_ALIAS); UserEnt = CurrentIndex(); IssueMessage(LOG_INFO, "%s logged in.", UserAlias); } } if (ClaimUser) { free(ClaimUser); ClaimUser = NULL; } if (Challenge) { free(Challenge); Challenge = NULL; } State = S_IDLE; Unlock(); } /*********************************************************************** * sleep til a given time ***********************************************************************/ void SleepTil(long theTime) { unsigned theSpan; theSpan = theTime - time((long *)0); if (0 < theSpan && theSpan < 10000) sleep(theSpan); } /*********************************************************************** * return the dir entry of the requested alias ***********************************************************************/ Dir GetAliasDir(char *theName) { Arg *theArgList; Arg *theArg; long *theEntry; static Dir theDir; theArg = theArgList = FreshArg(); theArg->aType = COMMAND; theArg->aFirst = make_str("query"); theArg->aNext = FreshArg(); theArg = theArg->aNext; theArg->aType = VALUE | EQUAL | VALUE2; theArg->aFirst = make_str("alias"); /* should be alias */ theArg->aSecond = make_str(theName); (void) ValidQuery(theArgList, C_QUERY); if ((theEntry = DoLookup(theArgList)) != NULL && length(theEntry) == 1 && next_ent(*theEntry)) getdata(&theDir); else theDir = NULL; if (theEntry) free((char *)theEntry); FreeArgs(theArgList); return (theDir); } /*********************************************************************** * de-identify the current user ***********************************************************************/ void DoLogout(Arg *theArg) { if (theArg->aNext) DoReply(LR_SYNTAX, "argument given on logout command."); else if (!User) DoReply(LR_ERROR, "Not logged in."); else { FreeDir(&User); DoReply(LR_OK, "Ok."); } } /*********************************************************************** * list fields ***********************************************************************/ void DoFields(Arg *theArg) { if (theArg->aNext == NULL) { ListAllFields(); DoReply(LR_OK, "Ok."); } else if (OkFields(theArg->aNext)) { for (theArg=theArg->aNext; theArg; theArg=theArg->aNext) if (theArg->aFD) ListField(theArg->aFD); DoReply(LR_OK, "Ok."); } else DoReply(LR_SYNTAX, "Invalid field request."); } /*********************************************************************** * List a single field ***********************************************************************/ void ListField(FieldDesc *theFD) { char scratch[MAX_LEN]; char *cp; char *strtok(); sprintf(scratch, "%d:%s:max %d", theFD->fdId, theFD->fdName, theFD->fdMax); cp = scratch + strlen(scratch); if (theFD->fdIndexed) cp += strcpc(cp, " Indexed"); if (theFD->fdLookup) cp += strcpc(cp, " Lookup"); if (theFD->fdPublic) cp += strcpc(cp, " Public"); if (theFD->fdDefault) cp += strcpc(cp, " Default"); if (theFD->fdAlways) cp += strcpc(cp, " Always"); if (theFD->fdAny) cp += strcpc(cp, " Any"); if (theFD->fdChange) cp += strcpc(cp, " Change"); if (theFD->fdSacred) cp += strcpc(cp, " Sacred"); if (theFD->fdTurn) cp += strcpc(cp, " Turn"); if (theFD->fdEncrypt) cp += strcpc(cp, " Encrypt"); if (theFD->fdNoPeople) cp += strcpc(cp, " NoPeople"); *cp = 0; DoReply(-LR_OK, scratch); strcpy(scratch, theFD->fdHelp); for (cp = strtok(scratch, "\n"); cp; cp = strtok((char *)NULL, "\n")) DoReply(-LR_OK, "%d:%s:%s", theFD->fdId, theFD->fdName, cp); } /*********************************************************************** * list all fields ***********************************************************************/ void ListAllFields(void) { FieldDesc **theFD; for (theFD = FieldDescriptors; *theFD; theFD++) ListField(*theFD); } /*********************************************************************** * validate arguments for field names ***********************************************************************/ int OkFields(Arg *theArgs) { int bad = 0; int count = 0; FieldDesc *theFD; for (; theArgs; theArgs = theArgs->aNext) { count++; if (theArgs->aType != VALUE) { DoReply(-LR_SYNTAX, "argument %d:is not a field name.", count); bad = 1; } else if (!(theFD = FindFD(theArgs->aFirst))) { DoReply(-LR_FIELD, "%s:unknown field.", theArgs->aFirst); bad = 1; } else theArgs->aFD = theFD; } return (!bad); } /*********************************************************************** * delete entries ***********************************************************************/ void DoDelete(Arg *theArg) { long *theEntries, *anEntry; int haveError = 0; int count; int done; Dir theDir; if (!AmHero && !User) { DoReply(LR_NOTLOG, "Must be logged in to delete."); return; } else if (!UserCanDelete()) { DoReply(LR_ERROR, "You may not delete entries."); IssueMessage(LOG_INFO, "%s is not authorized to delete entries.", UserAlias); return; } if (!ValidQuery(theArg, C_DELETE)) { DoReply(LR_SYNTAX, "Delete command not understood."); return; } if (!GonnaWrite()) { /* GonnaWrite will issue an error message */ ; return; } if ((theEntries = DoLookup(theArg)) == NULL) { DoReply(LR_NOMATCH, "No entries matched specifications."); Unlock(); return; } for (count=1,done=0,anEntry=theEntries; *anEntry; count++, anEntry++) { if (!next_ent(*anEntry)) { DoReply(-LR_TEMP, "Internal error."); haveError = 1; continue; } getdata(&theDir); if (!CanDelete(theDir)) { DoReply(-LR_ERROR, "%d:%s: you may not delete this entry.", count, FindValue(theDir, F_ALIAS)); haveError = 1; IssueMessage(LOG_INFO, "%s may not delete %s.", UserAlias, FindValue(theDir, F_ALIAS)); continue; } /* delete the index entries */ MakeLookup(theDir, *anEntry, unmake_lookup); FreeDir(&theDir); /* mark it as dead and put it out to pasture */ SetDeleteMark(); set_date(1); store_ent(); done++; } free((char *)theEntries); Unlock(); if (haveError) DoReply(LR_ERROR, "%d errors, %d successes on delete command.", count - done, done); else DoReply(LR_OK, "%d entries deleted.", done); } /*********************************************************************** * open a temp file for output ***********************************************************************/ int OpenTempOut(void) { char *make_str(); char *mktemp(); if (TFile == NULL) { TFile = make_str(Tempfile); mktemp(TFile); } if ((TempOutput = fopen(TFile, "w+")) == NULL) { free(TFile); TFile = NULL; return (0); } unlink(TFile); return (1); } /*********************************************************************** * Dump a the stuff in TFile to output ***********************************************************************/ void DumpOutput(void) { int c; rewind(TempOutput); /* back to the beginning */ { while ((c = getc(TempOutput)) != EOF) putc(c, Output); } fclose(TempOutput); /* close; already unlinked */ fflush(Output); } /*********************************************************************** * print the current command ***********************************************************************/ void PrintCommand(int theCommand,Arg *theArgs) { fprintf(Output, "%d: %s", LR_ECHO, theArgs->aFirst); for (theArgs = theArgs->aNext; theArgs; theArgs = theArgs->aNext) { putc(' ', Output); if (theArgs->aType == RETURN) fputs(theCommand == C_QUERY ? "return" : "make", Output); else { if (theArgs->aType & VALUE) fputs(theArgs->aFirst, Output); d757 3 a759 3 if (theArgs->aType & TILD_E) putc('~', Output); else d761 61 a821 56 if (theArgs->aType & EQUAL) putc('=', Output); if (theArgs->aType & VALUE2) fputs(theArgs->aSecond, Output); } } putc('\n', Output); } /*********************************************************************** * was the returned string encrypted with the appropriate password? ***********************************************************************/ int UserMatch(char *string) { char decrypted[MAXSTR]; char *decrypt(); char *pw = PasswordOf(User); if (!*pw) return(0); crypt_start(pw); (void) decrypt(decrypted, string); return (!strcmp(decrypted, Challenge)); } /*********************************************************************** * generate a random string ***********************************************************************/ char *RandomString(int byteCount) { static char string[MAXSTR]; char *cp; static int seeded = 0; if (!seeded) { seeded = 1; srandom((int)time((long *)NULL) ^ getpid()); } for (cp = string; byteCount; cp++, byteCount--) *cp = (random() & 0x3f) + 0x21; return (string); } /*********************************************************************** * extract the password form a dir ***********************************************************************/ char *PasswordOf(Dir User) { int len; char *password; /* find the user's password */ if (!*(password = FindValue(User, F_PASSWORD))) { d823 6 a828 7 if (*(password = FindValue(User, F_UNIVID))) { len = strlen(password); if (len > 8) password += len - 8; } else d830 3 a832 3 password = ""; } return (password); d836 1 a836 1 /************************************************************************ d839 26 a864 23 int OkByEmail(Dir User,char *username) { char buf[256]; char *email=FindValue(User,F_EMAIL); int result; if (!TrustHostEnt || !*email) result = 1; else { sprintf(buf,"%s@@%s",username,TrustHostEnt->h_name); result = strcmp(email,buf); } if (result) { if (ReadOnly) { DoReply(LR_READONLY, "login not allowed to read-only database."); result = 1; } else DoReply(LR_NOEMAIL,"You can't login that way."); } return(!result); d866 1 a867 1 @ 1.30 log @Last Dorner changes. @ text @d2 1 a2 1 /***********************************************************************/ d368 2 a369 2 || ((*me=='e'||*me=='E')&&!OkByEmail(User,theArg->aFirst))) #else a370 1 #endif @ 1.29 log @No help here. @ text @d11 1 d16 2 a25 1 extern char *Database; /* conf.c */ a29 1 extern char *Tempfile; /* conf.c */ d34 3 d58 2 d86 1 a86 1 if (LastArg->aType == 1 && theType == EQUAL) d88 1 a88 2 else if (LastArg->aType == EQUAL || LastArg->aType == (VALUE | EQUAL)) d128 1 a128 1 if (Daemon && GetState(Database)) d143 1 a143 1 if (DiscardIt || theCommand != C_ANSWER && theCommand != C_CLEAR) d145 1 a145 1 DoReply(-LR_NOANSWER, "Expecting answer or clear; login discarded."); d194 1 a194 1 bzero(theArg,sizeof(Arg)); d204 14 d248 14 a285 2 if (theCode > 0) IssueMessage(LOG_DEBUG, "%d", theCode); d287 7 a314 3 if (ReadOnly) DoReply(LR_READONLY, "login not allowed to read-only database."); else d340 1 a340 2 else if (!theArg) d342 1 a342 2 else if (theArg->aType != VALUE) d344 1 a344 2 else if (!GonnaRead()) d354 4 a357 1 DoReply(LR_ERROR, "Login failed."); d360 12 a371 3 else if (((*me=='a' || *me=='A') && !UserMatch(theArg->aFirst)) || ((*me=='c'||*me=='C') && strcmp(theArg->aFirst,PasswordOf(User)))) d374 15 a388 2 DoReply(LR_ERROR, "Login failed."); IssueMessage(LOG_INFO, "Password incorrect for %s.", ClaimUser); d531 1 a531 1 if (theFD->fdEncrypt) d584 1 a584 1 long *theEntries; d622 1 a622 1 for (count = 1, done = 0; *theEntries; count++, theEntries++) d624 1 a624 1 if (!next_ent(*theEntries)) d642 1 a642 1 MakeLookup(theDir, *theEntries, unmake_lookup); d721 5 d782 1 d790 1 d795 31 @ 1.28 log @No help here. @ text @d1 1 d14 1 a20 1 static Arg *OldArgs = NULL; a21 5 static int HasHistory = 0; char *make_str(); char *PasswordOf(); Arg *FreshArg(); char **getdata(); d38 1 a38 1 int (*CommandTable[]) () = d54 1 a54 1 0 d70 1 a70 3 AddValue(theValue, theType) char *theValue; int theType; a71 4 Arg *historyArgs; Arg *RememberArg(); HasHistory = HasHistory || *theValue == HISTORY; d74 3 a76 14 if (*theValue == HISTORY && (TheArgs == RememberArg(theValue))) { /* RememberArg has given us an Arg list. Point LastArg at end. */ for (LastArg->aNext = TheArgs; LastArg->aNext; LastArg = LastArg->aNext) ; } else { LastArg = TheArgs = FreshArg(); LastArg->aFirst = make_str(theValue); LastArg->aType = theType; } a78 1 if (*theValue == HISTORY && (historyArgs = RememberArg(theValue))) a79 6 /* RememberArg has given us an Arg list. Point LastArg at the end. */ for (LastArg->aNext = historyArgs; LastArg->aNext; LastArg = LastArg->aNext) ; } else { d101 1 a101 2 Unknown(theJunk) char *theJunk; d109 1 a109 2 DoCommand(theCommand) int theCommand; d120 1 a120 2 if (InputType == IT_FILE || InputType == IT_PIPE || OP_VALUE(ECHO_OP) || HasHistory) d157 1 a157 2 FreeArgs(OldArgs); OldArgs = TheArgs; d159 1 a159 1 HasHistory = DiscardIt = 0; d165 1 a165 2 FreeArgs(theArg) Arg *theArg; d184 1 a184 2 Arg * FreshArg() d189 1 a189 6 theArg->aFirst = NULL; theArg->aSecond = NULL; theArg->aType = NULL; theArg->aKey = NULL; theArg->aFD = NULL; theArg->aNext = NULL; d197 1 a197 2 DoStatus(theArg) Arg *theArg; d210 1 a210 2 DoId(theArg) Arg *theArg; d219 1 a219 2 DoQuit(theArg) Arg *theArg; d223 1 d231 1 a231 2 NotImplemented(theArg) Arg *theArg; d240 1 a240 4 DoReply(theCode, theFormat, theArgs) int theCode; char *theFormat; char *theArgs; d243 2 a244 1 d247 6 a252 1 _doprnt(scratchFormat, &theArgs, TempOutput); d254 2 a255 1 IssueMessage(LOG_INFO, "%d", theCode); d261 1 a261 2 DoLogin(theArg) Arg *theArg; d295 1 a295 2 DoAnswer(theArg) Arg *theArg; d361 1 a361 2 SleepTil(theTime) long theTime; d373 1 a373 3 Dir GetAliasDir(theName) char *theName; d407 1 a407 2 DoLogout(theArg) Arg *theArg; d424 1 a424 2 DoFields(theArg) Arg *theArg; d446 1 a446 2 ListField(theFD) FieldDesc *theFD; d486 1 a486 1 ListAllFields() d497 1 a497 2 OkFields(theArgs) Arg *theArgs; d525 1 a525 2 DoDelete(theArgs) Arg *theArgs; a531 1 int unmake_lookup(); d546 1 a546 1 if (!ValidQuery(theArgs, C_DELETE)) d558 1 a558 1 if ((theEntries = DoLookup(theArgs)) == NULL) d608 1 a608 1 OpenTempOut() d634 1 a634 1 DumpOutput() a647 154 * retrieve specified argument(s) from the old argument list ***********************************************************************/ Arg * RememberArg(theSelector) char *theSelector; { Arg *theArgs; Arg *anArg; Arg *oldArg; Arg *CopyArg(); int firstNumber; int n; if (!OldArgs) return (NULL); theSelector++; /* skip the ! */ switch (*theSelector) { case 'q': /* request the query portion */ oldArg = OldArgs->aNext; if (!oldArg) return (NULL); anArg = theArgs = CopyArg(oldArg); for (oldArg = oldArg->aNext; oldArg && oldArg->aType != RETURN; oldArg = oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg = anArg->aNext; } break; case 'r': /* the return portion */ oldArg = OldArgs->aNext; if (!oldArg) return (NULL); /* skip to the return token */ for (oldArg = oldArg->aNext; oldArg && oldArg->aType != RETURN; oldArg = oldArg->aNext); if (!oldArg || !oldArg->aNext) return (NULL); oldArg = oldArg->aNext; anArg = theArgs = CopyArg(oldArg); for (oldArg = oldArg->aNext; oldArg; oldArg = oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg = anArg->aNext; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = firstNumber = atoi(theSelector); for (oldArg = OldArgs; n && oldArg; n--) oldArg = oldArg->aNext; if (!oldArg) return (NULL); while (isdigit(*theSelector)) theSelector++; if (!*theSelector) theArgs = CopyArg(oldArg); else if (*theSelector != '-') return (NULL); /* syntax error */ else { theSelector++; if (!*theSelector) { /* copy'em all */ theArgs = anArg = CopyArg(oldArg); for (oldArg = oldArg->aNext; oldArg; oldArg = oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg = anArg->aNext; } } else { n = atoi(theSelector) - firstNumber; /* how many? */ /* do we have that many? */ for (anArg = oldArg; n > 0 && anArg; n--, anArg = anArg->aNext); if (n) return (NULL); /* nope. */ n = atoi(theSelector) - firstNumber; /* how many? */ theArgs = anArg = CopyArg(oldArg); for (oldArg = oldArg->aNext; n; n--, oldArg = oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg = anArg->aNext; } } } break; default: return (NULL); } return (theArgs); } /*********************************************************************** * make a copy of an argument structure ***********************************************************************/ Arg * CopyArg(theArg) Arg *theArg; { Arg *newArg; newArg = FreshArg(); newArg->aType = theArg->aType; newArg->aKey = theArg->aKey; if (theArg->aFirst) newArg->aFirst = make_str(theArg->aFirst); if (theArg->aSecond) newArg->aSecond = make_str(theArg->aSecond); newArg->aFD = theArg->aFD; newArg->aRating = newArg->aRating; return (newArg); } /*********************************************************************** d650 1 a650 3 PrintCommand(theCommand, theArgs) int theCommand; Arg *theArgs; d676 1 a676 2 UserMatch(string) char *string; d691 1 a691 3 char * RandomString(byteCount) int byteCount; d712 1 a712 3 char * PasswordOf(User) Dir User; @ 1.27 log @No help here. @ text @d57 1 d132 1 a132 1 fprintf(Output, "%d:%s:%s\n", LR_SYNTAX, theJunk, "Command not recognized."); d141 6 d149 1 d169 1 a169 1 if (DiscardIt || theCommand != C_ANSWER) d171 1 a171 1 DoReply(-LR_NOANSWER, "Expecting answer; login discarded."); d323 1 d366 2 a367 1 if (!UserMatch(theArg->aFirst)) d520 2 d886 1 d888 2 a889 1 crypt_start(PasswordOf(User)); d937 1 a937 1 password = "secret"; @ 1.26 log @No help here. @ text @d56 1 d255 2 a256 2 DoReply(LR_OK, "Bye!"); DumpOutput(); d470 2 a471 1 ListField(theArg->aFD); d548 1 a548 1 DoReply(-LR_FIELD, "%d:unknown field.", theArgs->aFirst); @ 1.25 log @No help here. @ text @d13 4 a16 4 #include "../Include/commands.h" #include "../Include/options.h" #include "../Include/field.h" #include "../Include/qi.h" d162 1 a162 1 DoReply(LR_SYNTAX, "Expecting answer; login discarded."); d194 1 a194 3 for (theNext = theArg->aNext; theArg; theArg = theNext, theNext = theArg->aNext) d196 1 d468 1 a468 1 for (theArg = theArg->aNext; theArg; theArg = theArg->aNext) d496 4 @ 1.24 log @No help here. @ text @d13 4 a16 4 #include "../include/commands.h" #include "../include/options.h" #include "../include/field.h" #include "../include/qi.h" @ 1.23 log @No help here. @ text @a68 3 char *Hero = "uiuc"; /* magic hero entry */ Dir HeroDir = 0; /* Hero's Dir */ d368 1 a368 1 AmHero = !stricmp(ClaimUser, Hero); @ 1.22 log @No help here. @ text @d1 9 a9 6 /*********************************************************************** * This software is Copyright (C) 1988 by Steven Dorner and the University * of Illinois Board of Trustees. No warranties expressed or implied, no * support provided. Please do not redistribute it in its present form. * Contact me for details (dorner@@garcon.cso.uiuc.edu). ***********************************************************************/ d143 1 a143 1 syslog(LOG_INFO, "%s", CommandText); d157 1 a157 1 syslog(LOG_INFO, "Couldn't open temp file.\n"); d288 1 a288 1 syslog(LOG_INFO, "%d", theCode); d357 1 a357 1 syslog(LOG_INFO, "login: alias %s does not exist.", ClaimUser); d364 1 a364 1 syslog(LOG_INFO, "Password incorrect for %s.", ClaimUser); d374 1 a374 1 syslog(LOG_INFO, "%s logged in.", UserAlias); d577 1 a577 1 syslog(LOG_INFO, "%s is not authorized to delete entries.", UserAlias); d614 1 a614 1 syslog(LOG_INFO, "%s may not delete %s.", @ 1.21 log @No help here. @ text @d21 1 a21 1 Arg *FreshArg(); d24 10 a33 10 extern char *Database; /* conf.c */ extern FILE *Input; /* mqi.c */ extern FILE *Output; /* mqi.c */ extern int InputType; /* mqi.c */ extern char Foreign[80]; /* mqi.c */ extern char *Tempfile; /* conf.c */ extern char CommandText[]; /* language.l */ extern char *CommandSpot; /* language.l */ extern int Daemon; /* mqi.c */ extern char *DBState; /* mqi.c */ d38 2 a39 2 int DiscardIt; int (*CommandTable[]) () = d41 13 a53 13 DoQuery, DoChange, DoLogin, DoAnswer, DoLogout, DoFields, DoAdd, DoDelete, DoSet, DoQuit, DoStatus, DoId, 0 d56 4 a59 4 Dir User = 0; /* the currently logged in user */ int AmHero = 0; /* is currently logged in user the Hero? */ char *UserAlias = 0; /* the alias of the currently logged in user */ int UserEnt = 0; /* entry number of current user */ d61 4 a64 4 char *ClaimUser = 0; /* the identity the user has claimed, but not * yet verified */ char *Challenge = 0; /* challenge string */ int State = S_IDLE; d66 2 a67 2 char *Hero = "uiuc"; /* magic hero entry */ Dir HeroDir = 0; /* Hero's Dir */ d74 1 a74 1 int theType; d76 2 a77 2 Arg *historyArgs; Arg *RememberArg(); d79 4 a82 2 HasHistory = HasHistory || *theValue == HISTORY; if (!TheArgs) d84 5 a88 14 if (*theValue == HISTORY && (TheArgs == RememberArg(theValue))) { /* RememberArg has given us an Arg list. Point LastArg at end. */ for (LastArg->aNext = TheArgs; LastArg->aNext; LastArg = LastArg->aNext) ; } else { LastArg = TheArgs = FreshArg(); LastArg->aFirst = make_str(theValue); LastArg->aType = theType; } a90 1 if (*theValue == HISTORY && (historyArgs = RememberArg(theValue))) d92 3 a94 3 /* RememberArg has given us an Arg list. Point LastArg at the end. */ for (LastArg->aNext = historyArgs; LastArg->aNext; LastArg = LastArg->aNext) ; d96 12 d109 1 d111 2 a112 15 if (LastArg->aType == 1 && theType == EQUAL) LastArg->aType |= theType; else if (LastArg->aType == EQUAL || LastArg->aType == (VALUE | EQUAL)) { LastArg->aType |= VALUE2; LastArg->aSecond = make_str(theValue); } else { LastArg->aNext = FreshArg(); LastArg = LastArg->aNext; LastArg->aType = theType; LastArg->aFirst = make_str(theValue); } d114 8 d130 1 a130 1 fprintf(Output, "%d:%s:%s\n", LR_SYNTAX, theJunk, "Command not recognized."); d137 1 a137 1 int theCommand; d139 5 a143 2 char *GetState(); char *theState; d145 5 a149 5 *CommandSpot = '\0'; syslog(LOG_INFO, "%s", CommandText); if (InputType == IT_FILE || InputType == IT_PIPE || OP_VALUE(ECHO_OP) || HasHistory) PrintCommand(theCommand, TheArgs); /* echo the cmd */ d151 6 a156 5 if (Daemon && (theState = GetState(Database))) { fprintf(Output, "555:Database shut off (%s).\n", theState); exit(0); } d158 3 a160 1 if (!OpenTempOut()) d162 6 a167 3 fprintf(Output, "%d:couldn't open temp file.\n", LR_INTERNAL); syslog(LOG_INFO, "Couldn't open temp file.\n"); goto done; d169 1 d171 4 a174 12 if (State == S_E_PENDING) { if (DiscardIt || theCommand != C_ANSWER) { DoReply(LR_SYNTAX, "Expecting answer; login discarded."); State = S_IDLE; free(ClaimUser); ClaimUser = 0; free(Challenge); Challenge = 0; } } d176 1 a176 4 if (DiscardIt) DoReply(LR_SYNTAX, "Command not understood."); else (*CommandTable[theCommand - 1]) (TheArgs); a177 2 DumpOutput(); d179 4 a182 4 FreeArgs(OldArgs); OldArgs = TheArgs; TheArgs = NULL; HasHistory = DiscardIt = 0; d189 1 a189 1 Arg *theArg; d191 1 a191 1 Arg *theNext; d193 11 a203 11 if (theArg) for (theNext = theArg->aNext; theArg; theArg = theNext, theNext = theArg->aNext) { if (theArg->aFirst) free(theArg->aFirst); if (theArg->aSecond) free(theArg->aSecond); free((char *)theArg); } d209 1 a209 1 Arg * d212 1 a212 1 Arg *theArg; d214 8 a221 8 theArg = New(Arg); theArg->aFirst = NULL; theArg->aSecond = NULL; theArg->aType = NULL; theArg->aKey = NULL; theArg->aFD = NULL; theArg->aNext = NULL; return (theArg); d229 1 a229 1 Arg *theArg; d231 4 a234 4 if (ReadOnly) DoReply(LR_RONLY,"Database ready, read only (%s).", DBState); else DoReply(LR_OK,"Database ready."); d243 1 a243 1 Arg *theArg; d245 1 a245 1 DoReply(LR_OK,"Thanks."); d253 1 a253 1 Arg *theArg; d255 4 a258 4 DoReply(LR_OK, "Bye!"); DumpOutput(); closelog(); exit(0); d265 1 a265 1 Arg *theArg; d267 1 a267 1 DoReply(500, "%s:command not implemented.", theArg->aFirst); d275 1 a275 1 int theCode; d279 1 a279 1 char scratchFormat[256]; d281 1 a281 1 sprintf(scratchFormat, "%d:%s\n", theCode, theFormat); d283 3 a285 3 _doprnt(scratchFormat, &theArgs, TempOutput); if (theCode > 0) syslog(LOG_INFO, "%d", theCode); d292 1 a292 1 Arg *theArg; d294 2 a295 2 char *me; char *RandomString(); d297 22 a318 22 me = theArg->aFirst; theArg = theArg->aNext; /* skip the command name */ if (!theArg) DoReply(LR_SYNTAX, "%s:no name given.", me); else if (theArg->aType != VALUE) DoReply(LR_SYNTAX, "%s:argument invalid.", me); else if (theArg->aNext) DoReply(LR_SYNTAX, "%s:extra arguments.", me); else if (ReadOnly) DoReply(LR_READONLY, "login not allowed to read-only database."); else { Challenge = make_str(RandomString(40)); DoReply(LR_LOGIN, "%s", Challenge); ClaimUser = make_str(theArg->aFirst); State = S_E_PENDING; if (User) FreeDir(&User); } d326 1 a326 1 Arg *theArg; d328 2 a329 2 char *me; long time(), theTime; d331 2 a332 2 me = theArg->aFirst; theArg = theArg->aNext; d334 17 a350 12 if (!ClaimUser) DoReply(LR_SYNTAX, "%s:there is no outstanding login.", me); else if (!theArg) DoReply(LR_SYNTAX, "%s:no argument given.", me); else if (theArg->aType != VALUE) DoReply(LR_SYNTAX, "%s:invalid argument type.", me); else if (!GonnaRead()) /* Lock routines give their own errors */ ; else d352 3 a354 26 AmHero = 0; UserAlias = 0; theTime = time(NULL); if (!(User = GetAliasDir(ClaimUser))) { SleepTil(theTime + WAIT_SECS); DoReply(LR_ERROR, "Login failed."); syslog(LOG_INFO, "login: alias %s does not exist.", ClaimUser); } else if (!UserMatch(theArg->aFirst)) { SleepTil(theTime + WAIT_SECS); DoReply(LR_ERROR, "Login failed."); syslog(LOG_INFO, "Password incorrect for %s.", ClaimUser); FreeDir(&User); } else { SleepTil(theTime + WAIT_SECS); DoReply(LR_OK, "%s:Hi how are you?", ClaimUser); AmHero = !stricmp(ClaimUser, Hero); UserAlias = FindValue(User, F_ALIAS); UserEnt = CurrentIndex(); syslog(LOG_INFO, "%s logged in.", UserAlias); } d356 2 a357 1 if (ClaimUser) d359 4 a362 2 free(ClaimUser); ClaimUser = NULL; d364 1 a364 1 if (Challenge) d366 6 a371 2 free(Challenge); Challenge = NULL; d373 13 a385 2 State = S_IDLE; Unlock(); d392 1 a392 1 long theTime; d394 1 a394 1 unsigned theSpan; d396 3 a398 3 theSpan = theTime - time(0); if (0 < theSpan && theSpan < 10000) sleep(theSpan); d408 4 a411 4 Arg *theArgList; Arg *theArg; unsigned long *theEntry; static Dir theDir; d413 1 a413 1 theArg = theArgList = FreshArg(); d415 8 a422 8 theArg->aType = COMMAND; theArg->aFirst = make_str("query"); theArg->aNext = FreshArg(); theArg = theArg->aNext; theArg->aType = VALUE | EQUAL | VALUE2; theArg->aFirst = make_str("alias"); /* should be alias */ theArg->aSecond = make_str(theName); ValidQuery(theArgList, C_QUERY); d424 5 a428 5 if ((theEntry = DoLookup(theArgList)) != NULL && length(theEntry) == 1 && next_ent(*theEntry)) getdata(&theDir); else theDir = NULL; d430 3 a432 3 if (theEntry) free((char *)theEntry); FreeArgs(theArgList); d434 1 a434 1 return (theDir); d441 1 a441 1 Arg *theArg; d443 10 a452 10 if (theArg->aNext) DoReply(LR_SYNTAX, "argument given on logout command."); else if (!User) DoReply(LR_ERROR, "Not logged in."); else { FreeDir(&User); DoReply(LR_OK, "Ok."); } d459 1 a459 1 Arg *theArg; d461 14 a474 14 if (theArg->aNext == NULL) { ListAllFields(); DoReply(LR_OK, "Ok."); } else if (OkFields(theArg->aNext)) { for (theArg = theArg->aNext; theArg; theArg = theArg->aNext) ListField(theArg->aFD); DoReply(LR_OK, "Ok."); } else DoReply(LR_SYNTAX, "Invalid field request."); d483 3 a485 3 char scratch[MAX_LEN]; char *cp; char *strtok(); d487 23 a509 23 sprintf(scratch, "%d:%s:max %d", theFD->fdId, theFD->fdName, theFD->fdMax); cp = scratch + strlen(scratch); if (theFD->fdIndexed) cp += strcpc(cp, " Indexed"); if (theFD->fdLookup) cp += strcpc(cp, " Lookup"); if (theFD->fdPublic) cp += strcpc(cp, " Public"); if (theFD->fdDefault) cp += strcpc(cp, " Default"); if (theFD->fdChange) cp += strcpc(cp, " Change"); if (theFD->fdSacred) cp += strcpc(cp, " Sacred"); if (theFD->fdTurn) cp += strcpc(cp, " Turn"); if (theFD->fdEncrypt) cp += strcpc(cp, " Encrypt"); *cp = 0; DoReply(-LR_OK, scratch); strcpy(scratch, theFD->fdHelp); for (cp = strtok(scratch, "\n"); cp; cp = strtok(NULL, "\n")) DoReply(-LR_OK, "%d:%s:%s", theFD->fdId, theFD->fdName, cp); d517 1 a517 1 FieldDesc **theFD; d519 2 a520 2 for (theFD = FieldDescriptors; *theFD; theFD++) ListField(*theFD); d527 1 a527 1 Arg *theArgs; d529 3 a531 3 int bad = 0; int count = 0; FieldDesc *theFD; d533 4 a536 1 for (; theArgs; theArgs = theArgs->aNext) d538 2 a539 14 count++; if (theArgs->aType != VALUE) { DoReply(-LR_SYNTAX, "argument %d:is not a field name.", count); bad = 1; } else if (!(theFD = FindFD(theArgs->aFirst))) { DoReply(-LR_FIELD, "%d:unknown field.", theArgs->aFirst); bad = 1; } else theArgs->aFD = theFD; d541 9 a549 1 return (!bad); d556 1 a556 1 Arg *theArgs; d558 6 a563 6 unsigned long *theEntries; int haveError = 0; int count; int done; Dir theDir; int unmake_lookup(); d565 12 a576 12 if (!AmHero && !User) { DoReply(LR_NOTLOG, "Must be logged in to delete."); return; } else if (!UserCanDelete()) { DoReply(LR_ERROR, "You may not delete entries."); syslog(LOG_INFO, "%s is not authorized to delete entries.", UserAlias); return; } d578 5 a582 5 if (!ValidQuery(theArgs, C_DELETE)) { DoReply(LR_SYNTAX, "Delete command not understood."); return; } d584 16 a599 1 if (!GonnaWrite()) d601 3 a603 2 /* GonnaWrite will issue an error message */ ; return; d605 2 a606 2 if ((theEntries = DoLookup(theArgs)) == NULL) d608 6 a613 3 DoReply(LR_NOMATCH, "No entries matched specifications."); Unlock(); return; d616 3 a618 18 for (count = 1, done = 0; *theEntries; count++, theEntries++) { if (!next_ent(*theEntries)) { DoReply(-LR_TEMP, "Internal error."); haveError = 1; continue; } getdata(&theDir); if (!CanDelete(theDir)) { DoReply(-LR_ERROR, "%d:%s: you may not delete this entry.", count, FindValue(theDir, F_ALIAS)); haveError = 1; syslog(LOG_INFO, "%s may not delete %s.", UserAlias, FindValue(theDir, F_ALIAS)); continue; } d620 6 a625 3 /* delete the index entries */ MakeLookup(theDir, *theEntries, unmake_lookup); FreeDir(&theDir); d627 2 a628 5 /* mark it as dead and put it out to pasture */ SetDeleteMark(); store_ent(); done++; } d630 5 a634 8 free((char *)theEntries); Unlock(); if (haveError) DoReply(LR_ERROR, "%d errors, %d successes on delete command.", count - done, done); else DoReply(LR_OK, "%d entries deleted.", done); d642 2 a643 2 char *make_str(); char *mktemp(); d645 5 a649 5 if (TFile == NULL) { TFile = make_str(Tempfile); mktemp(TFile); } d651 6 a656 6 if ((TempOutput = fopen(TFile, "w+")) == NULL) { free(TFile); TFile = NULL; return (0); } d658 1 a658 1 unlink(TFile); d660 1 a660 1 return (1); d668 1 a668 1 int c; d670 7 a676 7 rewind(TempOutput); /* back to the beginning */ { while ((c = getc(TempOutput)) != EOF) putc(c, Output); } fclose(TempOutput); /* close; already unlinked */ fflush(Output); d682 1 a682 1 Arg * d686 6 a691 6 Arg *theArgs; Arg *anArg; Arg *oldArg; Arg *CopyArg(); int firstNumber; int n; d693 2 a694 2 if (!OldArgs) return (NULL); d696 1 a696 1 theSelector++; /* skip the ! */ d698 12 a709 1 switch (*theSelector) d711 4 a714 4 case 'q': /* request the query portion */ oldArg = OldArgs->aNext; if (!oldArg) return (NULL); d716 4 a719 1 anArg = theArgs = CopyArg(oldArg); d721 4 a724 8 for (oldArg = oldArg->aNext; oldArg && oldArg->aType != RETURN; oldArg = oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg = anArg->aNext; } break; d726 2 a727 4 case 'r': /* the return portion */ oldArg = OldArgs->aNext; if (!oldArg) return (NULL); d729 2 a730 4 /* skip to the return token */ for (oldArg = oldArg->aNext; oldArg && oldArg->aType != RETURN; oldArg = oldArg->aNext); d732 8 a739 2 if (!oldArg || !oldArg->aNext) return (NULL); d741 11 a751 2 oldArg = oldArg->aNext; anArg = theArgs = CopyArg(oldArg); d753 2 a754 8 for (oldArg = oldArg->aNext; oldArg; oldArg = oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg = anArg->aNext; } break; d756 2 a757 11 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = firstNumber = atoi(theSelector); d759 2 a760 2 for (oldArg = OldArgs; n && oldArg; n--) oldArg = oldArg->aNext; d762 12 a773 2 if (!oldArg) return (NULL); d775 3 a777 9 while (isdigit(*theSelector)) theSelector++; if (!*theSelector) theArgs = CopyArg(oldArg); else if (*theSelector != '-') return (NULL); /* syntax error */ else d779 7 a785 5 theSelector++; if (!*theSelector) { /* copy'em all */ theArgs = anArg = CopyArg(oldArg); d787 4 a790 11 for (oldArg = oldArg->aNext; oldArg; oldArg = oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg = anArg->aNext; } } else { n = atoi(theSelector) - firstNumber; /* how many? */ d792 8 a799 15 /* do we have that many? */ for (anArg = oldArg; n > 0 && anArg; n--, anArg = anArg->aNext); if (n) return (NULL); /* nope. */ n = atoi(theSelector) - firstNumber; /* how many? */ theArgs = anArg = CopyArg(oldArg); for (oldArg = oldArg->aNext; n; n--, oldArg = oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg = anArg->aNext; } } d801 1 a801 4 break; default: return (NULL); d803 1 d805 5 a809 1 return (theArgs); d815 1 a815 1 Arg * d817 1 a817 1 Arg *theArg; d819 1 a819 1 Arg *newArg; d821 10 a830 10 newArg = FreshArg(); newArg->aType = theArg->aType; newArg->aKey = theArg->aKey; if (theArg->aFirst) newArg->aFirst = make_str(theArg->aFirst); if (theArg->aSecond) newArg->aSecond = make_str(theArg->aSecond); newArg->aFD = theArg->aFD; newArg->aRating = newArg->aRating; return (newArg); d837 2 a838 2 int theCommand; Arg *theArgs; d840 9 a848 4 fprintf(Output, "%d: %s", LR_ECHO, theArgs->aFirst); for (theArgs = theArgs->aNext; theArgs; theArgs = theArgs->aNext) d850 6 a855 12 putc(' ', Output); if (theArgs->aType == RETURN) fputs(theCommand == C_QUERY ? "return" : "make", Output); else { if (theArgs->aType & VALUE) fputs(theArgs->aFirst, Output); if (theArgs->aType & EQUAL) putc('=', Output); if (theArgs->aType & VALUE2) fputs(theArgs->aSecond, Output); } d857 2 a858 1 putc('\n', Output); d867 2 a868 2 char decrypted[MAXSTR]; char *decrypt(); d870 3 a872 3 crypt_start(PasswordOf(User)); (void) decrypt(decrypted, string); return (!strcmp(decrypted, Challenge)); d880 1 a880 1 int byteCount; d882 3 a884 3 static char string[MAXSTR]; char *cp; static int seeded = 0; d886 5 a890 5 if (!seeded) { seeded = 1; srandom(time(NULL) ^ getpid()); } d892 2 a893 2 for (cp = string; byteCount; cp++, byteCount--) *cp = (random() & 0x3f) + 0x21; d895 1 a895 1 return (string); d903 1 a903 1 Dir User; d905 2 a906 2 int len; char *password; d908 4 a911 2 /* find the user's password */ if (!*(password = FindValue(User, F_PASSWORD))) d913 3 a915 8 if (*(password = FindValue(User, F_UNIVID))) { len = strlen(password); if (len > 8) password += len - 8; } else password = "secret"; d917 4 a920 1 return (password); @ 1.20 log @*** empty log message *** @ text @d1 6 d10 4 a13 4 #include "commands.h" #include "options.h" #include "field.h" #include "qi.h" @ 1.19 log @*** empty log message *** @ text @d27 1 d45 2 a143 1 fprintf(Output, "### 555 Database shut off (%s).\n", theState); d222 24 a254 2 fprintf(Output, "###\n"); fflush(Output); @ 1.18 log @*** empty log message *** @ text @a133 1 #ifndef ultrix a134 1 #endif a148 1 #ifndef ultrix a149 1 #endif a227 1 #ifndef ultrix a228 1 #endif a256 1 #ifndef ultrix a258 1 #endif a326 1 #ifndef ultrix a327 1 #endif a333 1 #ifndef ultrix a334 1 #endif a343 1 #ifndef ultrix a344 1 #endif a547 1 #ifndef ultrix a548 1 #endif a584 1 #ifndef ultrix a586 1 #endif @ 1.17 log @*** empty log message *** @ text @d134 1 d136 1 d151 1 d153 1 d232 1 d234 1 d263 1 d266 1 d335 1 d337 1 d344 1 d346 1 d356 1 d358 1 d490 2 d562 1 d564 1 d601 1 d604 1 @ 1.16 log @*** empty log message *** @ text @d2 1 d9 2 a10 2 static Arg *TheArgs=NULL; static Arg *OldArgs=NULL; d12 5 a16 5 static int DropIt=0; static int HasHistory=0; char *make_str(); char *PasswordOf(); Arg *FreshArg(); d18 3 a20 3 extern char *Database; /* conf.c */ extern FILE *Input; /* mqi.c */ extern FILE *Output; /* mqi.c */ d23 1 a23 1 extern char *Tempfile; /* conf.c */ d28 2 a29 2 FILE *TempOutput=0; static char *TFile=0; d31 2 a32 2 int DiscardIt; int (*CommandTable[])()= d34 11 a44 11 DoQuery, DoChange, DoLogin, DoAnswer, DoLogout, DoFields, DoAdd, DoDelete, DoSet, DoQuit, 0 d47 4 a50 4 Dir User=0; /* the currently logged in user */ int AmHero = 0; /* is currently logged in user the Hero? */ char *UserAlias=0; /* the alias of the currently logged in user */ int UserEnt=0; /* entry number of current user */ d52 4 a55 4 char *ClaimUser=0; /* the identity the user has claimed, but not yet verified */ char *Challenge=0; /* challenge string */ int State=S_IDLE; d57 2 a58 2 char *Hero="uiuc"; /* magic hero entry */ Dir HeroDir=0; /* Hero's Dir */ d63 3 a65 3 AddValue(theValue,theType) char *theValue; int theType; d67 2 a68 2 Arg *historyArgs; Arg *RememberArg(); d70 1 a70 1 HasHistory = HasHistory || *theValue==HISTORY; d73 1 a73 1 if (*theValue==HISTORY && (TheArgs==RememberArg(theValue))) d76 1 a76 1 for (LastArg->aNext=TheArgs; d78 1 a78 1 LastArg=LastArg->aNext) d83 1 a83 1 LastArg=TheArgs=FreshArg(); d88 2 a89 1 else if (*theValue==HISTORY && (historyArgs=RememberArg(theValue))) d92 1 a92 3 for (LastArg->aNext=historyArgs; LastArg->aNext; LastArg=LastArg->aNext) d97 1 a97 1 if (LastArg->aType==1 && theType==EQUAL) d99 2 a100 1 else if (LastArg->aType==EQUAL || LastArg->aType==(VALUE|EQUAL)) d119 1 a119 1 char *theJunk; d121 1 a121 1 fprintf(Output,"%d:%s:%s\n",LR_SYNTAX,theJunk,"Command not recognized."); d128 1 a128 1 int theCommand; d130 2 a131 2 char *GetState(); char *theState; d134 2 a135 2 syslog(LOG_INFO,"%s",CommandText); if (InputType==IT_FILE || InputType==IT_PIPE || OP_VALUE(ECHO_OP) || d137 1 a137 1 PrintCommand(theCommand,TheArgs); /* echo the cmd */ d139 1 a139 1 if (Daemon && (theState=GetState(Database))) d141 2 a142 2 fprintf(Output,"### 555 Database shut off (%s).\n",theState); fprintf(Output,"555:Database shut off (%s).\n",theState); d148 2 a149 2 fprintf(Output,"%d:couldn't open temp file.\n",LR_INTERNAL); syslog(LOG_INFO,"Couldn't open temp file.\n"); d153 1 a153 1 if (State==S_E_PENDING) d157 1 a157 1 DoReply(LR_SYNTAX,"Expecting answer; login discarded."); d167 1 a167 1 DoReply(LR_SYNTAX,"Command not understood."); d169 1 a169 1 (*CommandTable[theCommand-1])(TheArgs); d184 1 a184 1 Arg *theArg; d186 1 a186 1 Arg *theNext; d189 3 a191 3 for (theNext=theArg->aNext; theArg; theArg=theNext,theNext=theArg->aNext) d193 5 a197 3 if (theArg->aFirst) free(theArg->aFirst); if (theArg->aSecond) free(theArg->aSecond); free(theArg); d204 2 a205 1 Arg *FreshArg() d207 1 a207 1 Arg *theArg; d216 1 a216 1 return(theArg); d222 1 d224 1 a224 1 Arg *theArg; d226 1 a226 1 DoReply(LR_OK,"Bye!"); d229 1 a229 1 fprintf(Output,"###\n"); d238 1 a238 1 Arg *theArg; d240 1 a240 1 DoReply(500,"%s:command not implemented.",theArg->aFirst); d246 5 a250 4 DoReply(theCode,theFormat,theArgs) int theCode; char *theFormat; char *theArgs; d252 1 a252 1 char scratchFormat[256]; d254 1 a254 1 sprintf(scratchFormat,"%d:%s\n",theCode,theFormat); d257 2 a258 2 if (theCode>0) syslog(LOG_INFO,"%d",theCode); d265 1 a265 1 Arg *theArg; d267 2 a268 3 char *who; char *me; char *RandomString(); d273 1 a273 7 DoReply(LR_SYNTAX,"%s:no name given.",me); else if (theArg->aType!=VALUE) DoReply(LR_SYNTAX,"%s:argument invalid.",me); else if (theArg->aNext) DoReply(LR_SYNTAX,"%s:extra arguments.",me); else if (ReadOnly) DoReply(LR_READONLY,"login not allowed to read-only database."); d275 9 d286 1 a286 1 DoReply(LR_LOGIN,"%s",Challenge); /* this needs to change... */ d288 1 a288 1 State=S_E_PENDING; d299 1 a299 1 Arg *theArg; d301 2 a302 2 char *me; long time(),theTime; d308 1 a308 7 DoReply(LR_SYNTAX,"%s:there is no outstanding login.",me); else if (!theArg) DoReply(LR_SYNTAX,"%s:no argument given.",me); else if (theArg->aType!=VALUE) DoReply(LR_SYNTAX,"%s:invalid argument type.",me); else if (!GonnaRead()) /* Lock routines give their own errors */; d310 9 d323 1 a323 1 if (!(User=GetAliasDir(ClaimUser))) d325 3 a327 3 SleepTil(theTime+WAIT_SECS); DoReply(LR_ERROR,"Login failed."); syslog(LOG_INFO,"login: alias %s does not exist.",ClaimUser); d329 2 a330 1 else if (!UserMatch(theArg->aFirst)) d332 3 a334 3 SleepTil(theTime+WAIT_SECS); DoReply(LR_ERROR,"Login failed."); syslog(LOG_INFO,"Password incorrect for %s.",ClaimUser); d339 4 a342 4 SleepTil(theTime+WAIT_SECS); DoReply(LR_OK,"%s:Hi how are you?",ClaimUser); AmHero = !stricmp(ClaimUser,Hero); UserAlias = FindValue(User,F_ALIAS); d344 1 a344 1 syslog(LOG_INFO,"%s logged in.",UserAlias); d347 10 a356 2 if (ClaimUser) {free(ClaimUser);ClaimUser=NULL;} if (Challenge) {free(Challenge);Challenge=NULL;} d365 1 a365 1 long theTime; d367 1 a367 1 int theSpan; d379 1 a379 1 char *theName; d381 2 a382 2 Arg *theArgList; Arg *theArg; d393 1 a393 1 theArg->aFirst = make_str("alias"); /* should be alias */ d395 1 a395 1 ValidQuery(theArgList,C_QUERY); d397 1 a397 1 if ((theEntry=DoLookup(theArgList))!=NULL && length(theEntry)==1 && d403 2 a404 1 if (theEntry) free(theEntry); d407 1 a407 1 return(theDir); d414 1 a414 1 Arg *theArg; d417 1 a417 3 DoReply(LR_SYNTAX,"argument given on logout command."); else if (!User) DoReply(LR_ERROR,"Not logged in."); d419 3 d424 1 a424 1 DoReply(LR_OK,"Ok."); d432 1 a432 1 Arg *theArg; d434 1 a434 1 if (theArg->aNext==NULL) d437 1 a437 1 DoReply(LR_OK,"Ok."); d439 2 a440 1 else if (OkFields(theArg->aNext)) d442 1 a442 1 for (theArg=theArg->aNext;theArg;theArg=theArg->aNext) d444 1 a444 1 DoReply(LR_OK,"Ok."); d447 1 a447 1 DoReply(LR_SYNTAX,"Invalid field request."); d456 3 a458 3 char scratch[MAX_LEN]; char *cp; char *strtok(); d460 1 a460 1 sprintf(scratch,"%d:%s:max %d",theFD->fdId,theFD->fdName,theFD->fdMax); d462 14 a475 7 if (theFD->fdIndexed) cp += strcpc(cp," Indexed"); if (theFD->fdLookup) cp += strcpc(cp," Lookup"); if (theFD->fdPublic) cp += strcpc(cp," Public"); if (theFD->fdDefault) cp += strcpc(cp," Default"); if (theFD->fdChange) cp += strcpc(cp," Change"); if (theFD->fdSacred) cp += strcpc(cp," Sacred"); if (theFD->fdTurn) cp += strcpc(cp," Turn"); d477 4 a480 4 DoReply(-LR_OK,scratch); strcpy(scratch,theFD->fdHelp); for (cp=strtok(scratch,"\n");cp;cp=strtok(NULL,"\n")) DoReply(-LR_OK,"%d:%s:%s",theFD->fdId,theFD->fdName,cp); d490 1 a490 1 for (theFD=FieldDescriptors;*theFD;theFD++) d498 1 a498 1 Arg *theArgs; d500 2 a501 2 int bad=0; int count=0; d504 1 a504 1 for (;theArgs;theArgs=theArgs->aNext) d509 1 a509 1 DoReply(-LR_SYNTAX,"argument %d:is not a field name.",count); d512 2 a513 1 else if (!(theFD=FindFD(theArgs->aFirst))) d515 1 a515 1 DoReply(-LR_FIELD,"%d:unknown field.",theArgs->aFirst); d528 1 a528 1 Arg *theArgs; d531 5 a535 5 int haveError=0; int count; int done; Dir theDir; int unmake_lookup(); d539 1 a539 1 DoReply(LR_NOTLOG,"Must be logged in to delete."); d542 2 a543 1 else if (!UserCanDelete(User)) d545 2 a546 2 DoReply(LR_ERROR,"You may not delete entries."); syslog(LOG_INFO,"%s is not authorized to delete entries.",UserAlias); d549 2 a550 2 if (!ValidQuery(theArgs,C_DELETE)) d552 1 a552 1 DoReply(LR_SYNTAX,"Delete command not understood."); d558 1 a558 1 /* GonnaWrite will issue an error message */; d562 1 a562 1 if ((theEntries=DoLookup(theArgs))==NULL) d564 1 a564 1 DoReply(LR_NOMATCH,"No entries matched specifications."); d569 1 a569 1 for (count=1,done=0;*theEntries;count++,theEntries++) d573 1 a573 1 DoReply(-LR_TEMP,"Internal error."); d580 2 a581 2 DoReply(-LR_ERROR,"%d:%s: you may not delete this entry.", count,FindValue(theDir,F_ALIAS)); d583 2 a584 2 syslog(LOG_INFO,"%s may not delete %s.", UserAlias,FindValue(theDir,F_ALIAS)); d589 1 a589 1 MakeLookup(theDir,*theEntries,unmake_lookup); d598 1 a598 1 free(theEntries); d602 2 a603 2 DoReply(LR_ERROR,"%d errors, %d successes on delete command.", count-done,done); d605 1 a605 1 DoReply(LR_OK,"%d entries deleted.",done); d613 2 a614 1 char *make_str(); d616 1 a616 1 if (TFile==NULL) d618 1 a618 1 TFile=make_str(Tempfile); d622 1 a622 1 if ((TempOutput=fopen(TFile,"w+"))==NULL) d626 1 a626 1 return(0); d631 1 a631 1 return(1); d639 1 a639 1 int c; d643 2 a644 2 while ((c=getc(TempOutput))!=EOF) putc(c,Output); d653 1 a653 1 Arg * d655 1 a655 1 char *theSelector; d657 6 a662 7 Arg *theArgs; Arg *anArg; Arg *oldArg; Arg *CopyArg(); int firstNumber; int lastNumber; int n; d665 1 a665 1 return(NULL); d671 4 a674 4 case 'q': /* request the query portion */ oldArg = OldArgs->aNext; if (!oldArg) return(NULL); d676 1 a676 1 anArg=theArgs=CopyArg(oldArg); d678 8 a685 8 for (oldArg=oldArg->aNext; oldArg && oldArg->aType!=RETURN; oldArg=oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg=anArg->aNext; } break; d687 4 a690 4 case 'r': /* the return portion */ oldArg = OldArgs->aNext; if (!oldArg) return(NULL); d692 4 a695 4 /* skip to the return token */ for (oldArg=oldArg->aNext; oldArg && oldArg->aType!=RETURN; oldArg=oldArg->aNext); d697 2 a698 2 if (!oldArg || !oldArg->aNext) return(NULL); d700 2 a701 2 oldArg=oldArg->aNext; anArg=theArgs=CopyArg(oldArg); d703 8 a710 8 for (oldArg=oldArg->aNext; oldArg; oldArg=oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg=anArg->aNext; } break; d712 11 a722 17 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = firstNumber = atoi(theSelector); for (oldArg=OldArgs;n && oldArg;n--) oldArg=oldArg->aNext; if (!oldArg) return(NULL); d724 2 a725 1 while (isdigit(*theSelector)) theSelector++; d727 14 a741 4 theArgs = CopyArg(oldArg); else if (*theSelector!='-') return(NULL); /* syntax error */ else d743 6 a748 2 theSelector++; if (!*theSelector) d750 2 a751 10 /* copy'em all */ theArgs=anArg=CopyArg(oldArg); for (oldArg=oldArg->aNext; oldArg; oldArg=oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg=anArg->aNext; } d753 4 a756 3 else { n = atoi(theSelector) - firstNumber; /* how many? */ d758 4 a761 4 /* do we have that many? */ for (anArg=oldArg;n>0 && anArg;n--,anArg=anArg->aNext); if (n) return(NULL); /* nope. */ d763 8 a770 9 n = atoi(theSelector) - firstNumber; /* how many? */ theArgs=anArg=CopyArg(oldArg); for (oldArg=oldArg->aNext; n; n--,oldArg=oldArg->aNext) { anArg->aNext = CopyArg(oldArg); anArg = anArg->aNext; } d773 2 a774 1 break; d776 2 a777 2 default: return(NULL); d780 1 a780 1 return(theArgs); d786 1 a786 1 Arg * d788 1 a788 1 Arg *theArg; d790 1 a790 1 Arg *newArg; d801 1 a801 1 return(newArg); d807 3 a809 3 PrintCommand(theCommand,theArgs) int theCommand; Arg *theArgs; d811 2 a812 2 fprintf(Output,"%d: %s",LR_ECHO,theArgs->aFirst); for (theArgs=theArgs->aNext; d814 1 a814 1 theArgs=theArgs->aNext) d816 3 a818 3 putc(' ',Output); if (theArgs->aType==RETURN) fputs(theCommand==C_QUERY ? "return" : "make",Output); d822 1 a822 1 fputs(theArgs->aFirst,Output); d824 1 a824 1 putc('=',Output); d826 1 a826 1 fputs(theArgs->aSecond,Output); d829 1 a829 1 putc('\n',Output); d836 1 a836 1 char *string; d838 2 a839 1 char decrypted[MAXSTR]; d842 2 a843 2 decrypt(decrypted,string); return(!strcmp(decrypted,Challenge)); d849 1 a849 1 char * d851 1 a851 1 int byteCount; d854 2 a855 2 char *cp; static int seeded=0; d859 1 a859 1 seeded=1; a861 3 for (cp=string;byteCount;cp++,byteCount--) *cp = (random()&0x3f) + 0x21; d863 4 a866 1 return(string); d872 1 a872 1 char * d874 1 a874 1 Dir User; d876 2 a877 2 int len; char *password; d880 1 a880 1 if (!*(password=FindValue(User,F_PASSWORD))) d882 1 a882 1 if (*(password=FindValue(User,F_UNIVID))) d885 2 a886 1 if (len > 8) password += len-8; d889 1 a889 1 password="secret"; d891 1 a891 1 return(password); @ 1.15 log @*** empty log message *** @ text @d252 1 a252 1 syslog("%d",theCode); @ 1.14 log @*** empty log message *** @ text @d251 2 @ 1.13 log @*** empty log message *** @ text @d47 1 a47 1 int AmHero = 1; /* is currently logged in user the Hero? */ d307 1 a307 1 AmHero = 1; @ 1.12 log @*** empty log message *** @ text @d47 1 a47 1 int AmHero = 0; /* is currently logged in user the Hero? */ d307 1 a307 1 AmHero = 0; d504 1 a504 1 if (!User) @ 1.11 log @*** empty log message *** @ text @d14 1 a802 2 char *password; int len; d804 1 a804 12 /* find the user's password */ if (!*(password=FindValue(User,F_PASSWORD))) { if (*(password=FindValue(User,F_UNIVID))) { len = strlen(password); if (len > 8) password += len-8; } else password="secret"; } crypt_start(password); d830 24 @ 1.10 log @*** empty log message *** @ text @d312 1 a312 1 DoReply(LR_ERROR,"Die, hacker scum!"); d318 1 a318 1 DoReply(LR_ERROR,"Die, hacker scum!"); @ 1.9 log @*** empty log message *** @ text @d326 1 a326 1 AmHero = !strcmp(ClaimUser,Hero); @ 1.8 log @*** empty log message *** @ text @d55 1 a55 1 char *Hero="s-dorner"; /* magic hero entry */ @ 1.7 log @*** empty log message *** @ text @d55 1 a55 1 char *Hero="uiuc"; /* magic hero entry */ @ 1.6 log @*** empty log message *** @ text @d260 1 d274 1 a274 1 Challenge = make_str("secret"); d315 1 a315 1 else if (strcmp(theArg->aFirst,Challenge)) d793 49 @ 1.5 log @*** empty log message *** @ text @d2 1 d9 1 d12 1 d65 4 d71 14 a84 3 LastArg=TheArgs=FreshArg(); LastArg->aFirst = make_str(theValue); LastArg->aType = theType; d86 8 d133 3 a135 2 if (InputType==IT_FILE || InputType==IT_PIPE || OP_VALUE(ECHO_OP)) fprintf(Output,"%s",CommandText); /* echo the cmd */ d172 2 a173 1 FreeArgs(TheArgs); d175 1 a175 1 DiscardIt = 0; d247 1 a247 4 if (theCode<0) sprintf(scratchFormat,"%d-:%s\n",-theCode,theFormat); else sprintf(scratchFormat,"%d:%s\n",theCode,theFormat); d611 181 @ 1.4 log @*** empty log message *** @ text @d3 1 d107 2 a108 2 if (InputType==IT_FILE || InputType==IT_PIPE) fprintf(Output,"%s\n",CommandText); /* echo the cmd */ a184 5 /*********************************************************************** * command stubs ***********************************************************************/ DoSet(theArg) Arg *theArg; {NotImplemented(theArg);} @ 1.3 log @*** empty log message *** @ text @a590 8 /*********************************************************************** * complain about an old version of ph ***********************************************************************/ ComplainOld() { syslog(LOG_INFO,"Old ph."); } @ 1.2 log @*** empty log message *** @ text @d22 1 a22 1 static FILE *TempOutput=0; @ 1.1 log @Initial revision @ text @d12 1 d20 1 d101 3 d108 8 @