📄 userauth.cpp
字号:
// Copyright (C) 2006 David Sugar, Tycho Softworks.// // This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however// invalidate any other reasons why the executable file might be covered by// the GNU General Public License.//// This exception applies only to the code released under the name GNU// ccScript. If you copy code from other releases into a copy of GNU// ccScript, as the General Public License permits, the exception does// not apply to the code that you add in this way. To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU ccScript, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//#include "script3.h"#include <cstdio>#ifdef WIN32#define EXT_AUTH ".pwd"#define PRE_AUTH "\\Script Authorization\\"#define PRE_MAKE "\\Script Authorization"#else#define EXT_AUTH ""#define PRE_AUTH "/.access/"#define PRE_MAKE "/.access"#endifnamespace ccscript3Extension {using namespace std;using namespace ost; static Mutex authlock;/* From local_passwd.c (C) Regents of Univ. of California blah blah */static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static void to64(char *s, long v, int n){ while (--n >= 0) { *s++ = itoa64[v&0x3f]; v >>= 6; }}class LookupThread : public ScriptThread{private: FILE *fp; char path[128]; const char *key; const char *prefix; Symbol *sym; void run(void);public: LookupThread(ScriptInterp *interp, const char *group, Symbol *sym); ~LookupThread();}; class AuthorizeThread : public ScriptThread{private: FILE *fp; char path[128]; const char *user; const char *pass; const char *prefix; Symbol *sym; void run(void);public: AuthorizeThread(ScriptInterp *interp, const char *group, Symbol *sym); ~AuthorizeThread();};class PasswordThread : public ScriptThread{private: FILE *fp; char path[128]; const char *user; const char *pass; const char *save; void run(void);public: PasswordThread(ScriptInterp *interp, const char *group); ~PasswordThread();};class IdentifyThread : public ScriptThread{private: FILE *fp; const char *user; char path[128]; const char *prefix; void run(void);public: IdentifyThread(ScriptInterp *interp, const char *group); ~IdentifyThread();}; class UserauthChecks : public ScriptChecks{public: const char *chkAuthorize(Line *line, ScriptImage *img); const char *chkIdentify(Line *line, ScriptImage *img); const char *chkLogout(Line *line, ScriptImage *img); const char *chkLookup(Line *line, ScriptImage *img); const char *chkPassword(Line *line, ScriptImage *img);};class UserauthMethods : public ScriptMethods{public: bool scrAuthorize(void); bool scrIdentify(void); bool scrLogout(void); bool scrLookup(void); bool scrPassword(void);};class UserauthBinder : public ScriptBinder{public: UserauthBinder(Script::Define *run);};static Script::Define runtime[] = { {"authorize", false, (Script::Method)&UserauthMethods::scrAuthorize, (Script::Check)&UserauthChecks::chkAuthorize}, {"lookup", false, (Script::Method)&UserauthMethods::scrLookup, (Script::Check)&UserauthChecks::chkLookup}, {"identify", false, (Script::Method)&UserauthMethods::scrIdentify, (Script::Check)&UserauthChecks::chkIdentify}, {"password", false, (Script::Method)&UserauthMethods::scrPassword, (Script::Check)&UserauthChecks::chkPassword}, {"logout", true, (Script::Method)&UserauthMethods::scrLogout, (Script::Check)&UserauthChecks::chkLogout}, {NULL, false, NULL, NULL}};UserauthBinder::UserauthBinder(Script::Define *run) :ScriptBinder(run){ char path[128]; if(*Script::var_prefix != '.') { snprintf(path, sizeof(path), "%s" PRE_MAKE, Script::var_prefix); Dir::create(path); }}static UserauthBinder bindUserauth(runtime);LookupThread::LookupThread(ScriptInterp *interp, const char *group, Symbol *s) :ScriptThread(interp, 0){ key = interp->getValue(NULL); prefix = interp->getKeyword("prefix"); sym = s; if(*Script::var_prefix == '.') setString(path, sizeof(path), ".access"); else snprintf(path, sizeof(path), "%s" PRE_AUTH "%s" EXT_AUTH, Script::var_prefix, group); fp = NULL;}AuthorizeThread::AuthorizeThread(ScriptInterp *interp, const char *group, Symbol *s) :ScriptThread(interp, 0){ user = interp->getValue(NULL); pass = interp->getValue(NULL); prefix = interp->getKeyword("prefix"); sym = s; if(*Script::var_prefix == '.') setString(path, sizeof(path), ".access"); else snprintf(path, sizeof(path), "%s" PRE_AUTH "%s" EXT_AUTH, Script::var_prefix, group); fp = NULL;}PasswordThread::PasswordThread(ScriptInterp *interp, const char *group) :ScriptThread(interp, 0){ user = interp->getValue(NULL); pass = interp->getValue(NULL); save = interp->getValue(NULL); if(*Script::var_prefix == '.') setString(path, sizeof(path), ".access"); else snprintf(path, sizeof(path), "%s" PRE_AUTH "%s" EXT_AUTH, Script::var_prefix, group); fp = NULL;}IdentifyThread::IdentifyThread(ScriptInterp *interp, const char *group) :ScriptThread(interp, 0){ user = interp->getValue(NULL); prefix = interp->getKeyword("prefix"); if(*Script::var_prefix == '.') setString(path, sizeof(path), ".access"); else snprintf(path, sizeof(path), "%s" PRE_AUTH "%s" EXT_AUTH, Script::var_prefix, group); fp = NULL;}AuthorizeThread::~AuthorizeThread(){ terminate(); if(fp) ::fclose(fp);}PasswordThread::~PasswordThread(){ terminate(); if(fp) ::fclose(fp);}IdentifyThread::~IdentifyThread(){ terminate(); if(fp) ::fclose(fp);}LookupThread::~LookupThread(){ terminate(); if(fp) ::fclose(fp);}void AuthorizeThread::run(void){ char *tok, *uid = NULL, *pwd = NULL; time_t now; fp = ::fopen(path, "r"); if(!fp) { exitEvent("authorize:missing"); exit("authorize-missing"); } while(fp) { if(!fgets(path, sizeof(path), fp) || feof(fp)) { exitEvent("authorize:missing"); exit("authorize-missing"); } uid = strtok_r(path, ":\r\n", &tok); if(!uid) continue; if(!stricmp(uid, user)) { pwd = strtok_r(NULL, ":\r\n", &tok); break; } }#ifdef WIN32 if(stricmp(pass, pwd)) pass = NULL;#else authlock.enter(); pass = crypt(pass, pwd); if(stricmp(pass, pwd)) pass = NULL; authlock.leave();#endif if(!pass) { exitEvent("authorize:failed"); exit("authorize-failed"); } time(&now); --now; if(sym) snprintf(sym->data, 12, "%ld", (long)now); if(!prefix) exit(NULL); snprintf(path, sizeof(path), "%s/%s/%s", Script::var_prefix, prefix, uid); Dir::create(path); exit(NULL);}void PasswordThread::run(void){ char *tok = NULL, *uid = NULL, *pwd = NULL; char buf[128]; fpos_t fpos; time_t now; char salt[3]; char *cp; fp = ::fopen(path, "r+"); if(!fp) { exitEvent("password:missing"); exit("password-missing"); } while(fp) { fgetpos(fp, &fpos); if(!fgets(path, sizeof(path), fp) || feof(fp)) { exitEvent("password:missing"); exit("password-missing"); } setString(buf, sizeof(buf), path); uid = strtok_r(path, ":\r\n", &tok); if(!uid) continue; if(!stricmp(uid, user)) { pwd = strtok_r(NULL, ":\r\n", &tok); break; } }#ifdef WIN32 pass = NULL;#else if(stricmp(pass, "-")) { authlock.enter(); pass = crypt(pass, pwd); if(strcmp(pass, pwd)) pass = NULL; authlock.leave(); }#endif if(!pass) { exitEvent("password:failed"); exit("password-failed"); } time(&now); srand((int)now); to64(salt, rand(), 2); cp = strchr(buf, ':');#ifndef WIN32 authlock.enter(); strcpy(++cp, crypt(save, salt)); authlock.leave();#endif fsetpos(fp, &fpos); fputs(buf, fp); fflush(fp); exit(NULL);}void LookupThread::run(void){ char *tok, *uid, *pwd, *tag, *val; unsigned len; unsigned count = 0; char buf[128]; if(key && *key) fp = ::fopen(path, "r"); if(!fp || !sym) { exitEvent("lookup:missing"); exit("lookup-missing"); } len = strlen(key); for(;;) { if(!fgets(path, sizeof(path), fp) || feof(fp)) break; uid = strtok_r(path, ":\r\n", &tok); pwd = strtok_r(NULL, ":\r\n", &tok); tag = strtok_r(NULL, ":\r\n", &tok); val = strtok_r(NULL, ":\r\n", &tok); if(!tag) continue; if(!val) val = tag; if(strnicmp(key, tag, len)) continue; if(prefix) { snprintf(buf, sizeof(buf), "%s/%s/%s", Script::var_prefix, prefix, uid); Dir::create(buf); } snprintf(buf, sizeof(path), "%s,%s", uid, val); commit(sym, buf); Thread::yield(); ++count; } if(!count) exitEvent("lookup:missing"); exit(NULL);}void IdentifyThread::run(void){ char *tok, *uid; fp = ::fopen(path, "r"); if(!fp) { exitEvent("identify:missing"); exit("identify-missing"); } for(;;) { if(!fgets(path, sizeof(path), fp) || feof(fp)) { exitEvent("identify:missing"); exit("identify-missing"); } uid = strtok_r(path, ":\r\n", &tok); if(!uid) continue; if(stricmp(uid, user)) continue; if(prefix) { snprintf(path, sizeof(path), "%s/%s/%s", Script::var_prefix, prefix, uid); Dir::create(path); } exitEvent("identify:found"); exit(NULL); }}bool UserauthMethods::scrLogout(void){ Symbol *sym = mapSymbol("script.authorize", 0); if(sym) sym->data[0] = 0; advance(); return true;}bool UserauthMethods::scrAuthorize(void){ char buf[128]; Name *scr = getName(); const char *grp = getMember(); char *cp; Symbol *sym = mapSymbol("script.authorize", 0); if(!grp) { setString(buf, sizeof(buf), scr->name); cp = strchr(buf, ':'); if(cp) *cp = 0; grp = buf; } if(sym) sym->data[0] = 0; release(); new AuthorizeThread(dynamic_cast<ScriptInterp*>(this), grp, sym); return false;}bool UserauthMethods::scrPassword(void){ char buf[128]; Name *scr = getName(); const char *grp = getMember(); char *cp; if(!grp) { setString(buf, sizeof(buf), scr->name); cp = strchr(buf, ':'); if(cp) *cp = 0; grp = buf; } release(); new PasswordThread(dynamic_cast<ScriptInterp*>(this), grp); return false;}bool UserauthMethods::scrLookup(void){ char buf[128]; Name *scr = getName(); const char *grp = getMember(); char *cp; Symbol *sym; if(!grp) { setString(buf, sizeof(buf), scr->name); cp = strchr(buf, ':'); if(cp) *cp = 0; grp = buf; } sym = mapSymbol(getOption(), 0); if(!sym) { error("target-missing"); return true; } clear(sym); release(); new LookupThread(dynamic_cast<ScriptInterp*>(this), grp, sym); return false;}bool UserauthMethods::scrIdentify(void){ char buf[128]; Name *scr = getName(); const char *grp = getMember(); char *cp; if(!grp) { setString(buf, sizeof(buf), scr->name); cp = strchr(buf, ':'); if(cp) *cp = 0; grp = buf; } release(); new IdentifyThread(dynamic_cast<ScriptInterp*>(this), grp); return false;}const char *UserauthChecks::chkIdentify(Line *line, ScriptImage *img){ unsigned idx = 0; if(!useKeywords(line, "=prefix")) return "invalid keyword for identify"; if(!getOption(line, &idx)) return "user id missing"; if(getOption(line, &idx)) return "too many arguments for identify"; return NULL;}const char *UserauthChecks::chkLookup(Line *line, ScriptImage *img){ unsigned idx = 0; const char *cp; if(!useKeywords(line, "=prefix")) return "invalid keyword for lookup"; cp = getOption(line, &idx); if(!cp) return "destination array missing"; if(*cp != '%' && *cp != '&') return "destination not variable"; if(!getOption(line, &idx)) return "lookup key missing"; if(getOption(line, &idx)) return "too many arguments for lookup"; return NULL;}const char *UserauthChecks::chkAuthorize(Line *line, ScriptImage *img){ unsigned idx = 0; if(!useKeywords(line, "=prefix")) return "invalid keyword for authorize"; if(!getOption(line, &idx)) return "user id missing"; if(!getOption(line, &idx)) return "password missing"; if(getOption(line, &idx)) return "too many arguments for authorize"; return NULL;} const char *UserauthChecks::chkPassword(Line *line, ScriptImage *img){ unsigned idx = 0; if(hasKeywords(line)) return "password does not use keywords"; if(!getOption(line, &idx)) return "user id missing"; if(!getOption(line, &idx)) return "old password missing"; if(!getOption(line, &idx)) return "new password missing"; if(getOption(line, &idx)) return "too many arguments for authorize"; return NULL;} const char *UserauthChecks::chkLogout(Line *line, ScriptImage *img){ if(getMember(line)) return "logout has no members"; if(line->argc) return "logout has no arguments or keywords"; return NULL;}};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -