00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "config.h"
00019 #include "defines.h"
00020
00021 #include <db.h>
00022
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <ctype.h>
00027 #include <time.h>
00028
00029 #include <sys/stat.h>
00030 #include <sys/types.h>
00031
00032 #include <pthread.h>
00033
00034 #include "cf_pthread.h"
00035
00036 #include "readline.h"
00037 #include "hashlib.h"
00038 #include "utils.h"
00039 #include "configparser.h"
00040 #include "readline.h"
00041 #include "fo_server.h"
00042 #include "serverlib.h"
00043
00044
00045 static DB *NamesDB = NULL;
00046 static u_char *AuthNames = NULL;
00047
00048 u_char *transform(const u_char *val) {
00049 register u_char *ptr = (u_char *)val;
00050 register int ws = 0;
00051 t_string str;
00052
00053 if(!ptr) return NULL;
00054
00055 str_init(&str);
00056
00057 for(;*ptr;ptr++) {
00058 if(isspace(*ptr)) {
00059 if(ws == 0) str_char_append(&str,*ptr);
00060 ws = 1;
00061 }
00062 else {
00063 ws = 0;
00064 str_char_append(&str,tolower(*ptr));
00065 }
00066 }
00067
00068
00069 while(isspace(str.content[str.len-1])) str.len--;
00070 str.content[str.len] = '\0';
00071
00072 ptr = str.content;
00073 while(isspace(*ptr)) ptr++;
00074
00075 return ptr;
00076 }
00077
00078 int check_auth(u_char *name,u_char *pass) {
00079 DBT key,data;
00080 int ret;
00081
00082 memset(&key,0,sizeof(key));
00083 memset(&data,0,sizeof(data));
00084
00085 key.data = name;
00086 key.size = strlen(name);
00087
00088 if((ret = NamesDB->get(NamesDB,NULL,&key,&data,0)) != 0) {
00089 if(ret != DB_NOTFOUND) cf_log(LOG_ERR,__FILE__,__LINE__,"db->get: %s\n",db_strerror(ret));
00090 return ret == DB_NOTFOUND ? 0 : -1;
00091 }
00092
00093 if(!pass) return 1;
00094 if(cf_strcmp(data.data,pass) == 0) return 0;
00095
00096 return 1;
00097 }
00098
00099 unsigned long long hashval(DB *db,u_char *key,size_t length) {
00100 return lookup(key,length,0);
00101 }
00102
00103 int flt_registerednames_handler(int connfd,const u_char **tokens,int tnum,rline_t *tsd) {
00104 u_char *ln = NULL,*tmp,*names[2],*pass;
00105 long llen;
00106 t_cf_hash *infos;
00107 DBT key,data;
00108 int ret;
00109
00110 memset(&key,0,sizeof(key));
00111 memset(&data,0,sizeof(data));
00112
00113 if(cf_strcmp(tokens[0],"AUTH") == 0) {
00114 infos = cf_hash_new(NULL);
00115
00116 do {
00117 ln = readline(connfd,tsd);
00118 if(ln) {
00119 llen = tsd->rl_len;
00120 while(ln[llen] != '\n') ln[llen--] = '\0';
00121 ln[llen--] = '\0';
00122
00123 tmp = strstr(ln,":");
00124
00125 if(tmp) {
00126 cf_hash_set(infos,ln,tmp-ln,tmp+2,llen-(int)(tmp-ln));
00127 }
00128 else {
00129 if(*ln == '\0') break;
00130
00131 free(ln);
00132 ln = NULL;
00133 writen(connfd,"503 Bad request\n",16);
00134 break;
00135 }
00136
00137 free(ln);
00138 }
00139 } while(ln);
00140
00141 if(ln) {
00142 if(tnum == 2 || tnum == 3) {
00143 if(cf_strncmp(tokens[1],"CHECK",5) == 0) {
00144 names[0] = transform(cf_hash_get(infos,"Name",4));
00145 pass = cf_hash_get(infos,"Pass",4);
00146
00147 if(!names[0]) {
00148 writen(connfd,"503 Bad request\n",16);
00149 }
00150 else {
00151 if(check_auth(names[0],pass) == 0) writen(connfd,"200 Ok\n",7);
00152 else writen(connfd,"504 Auth required\n",18);
00153 }
00154 }
00155 else if(cf_strncmp(tokens[1],"DELETE",6) == 0) {
00156 names[0] = transform(cf_hash_get(infos,"Name",4));
00157 pass = cf_hash_get(infos,"Pass",4);
00158
00159 if(!names[0] || (!pass && tnum != 3)) {
00160 writen(connfd,"504 Auth required\n",18);
00161 }
00162 else {
00163 if(tnum != 3 && check_auth(names[0],pass) != 0) {
00164 writen(connfd,"504 Auth required\n",18);
00165 }
00166 else {
00167 key.data = names[0];
00168 key.size = strlen(names[0]);
00169 if((ret = NamesDB->del(NamesDB,NULL,&key,0)) != 0) {
00170 if(ret != DB_NOTFOUND) cf_log(LOG_ERR,__FILE__,__LINE__,"DB->del: %s\n",db_strerror(ret));
00171 writen(connfd,"504 Auth required\n",18);
00172 }
00173 else {
00174 writen(connfd,"200 Ok\n",7);
00175 }
00176 }
00177 }
00178 }
00179 else if(cf_strncmp(tokens[1],"SET",3) == 0) {
00180 names[0] = transform(cf_hash_get(infos,"Name",4));
00181 names[1] = transform(cf_hash_get(infos,"New-Name",8));
00182 pass = cf_hash_get(infos,"Pass",4);
00183
00184 if(!names[1] || !pass) {
00185 writen(connfd,"504 Auth required\n",18);
00186 }
00187 else {
00188 if(names[0]) {
00189 if(check_auth(names[0],pass) == 0) {
00190
00191 key.data = names[1];
00192 key.size = strlen(names[1]);
00193
00194 if((ret = NamesDB->get(NamesDB,NULL,&key,&data,0)) == 0) {
00195 writen(connfd,"504 Auth required\n",18);
00196 }
00197 else {
00198 if(ret == DB_NOTFOUND) {
00199 data.data = pass;
00200 data.size = strlen(pass)+1;
00201 if((ret = NamesDB->put(NamesDB,NULL,&key,&data,0)) != 0) {
00202 cf_log(LOG_ERR,__FILE__,__LINE__,"DB->put: %s\n",db_strerror(ret));
00203 writen(connfd,"504 Auth required\n",18);
00204 }
00205 else {
00206 writen(connfd,"200 Ok\n",7);
00207
00208 key.data = names[0];
00209 key.size = strlen(names[0]);
00210
00211 if((ret = NamesDB->del(NamesDB,NULL,&key,0)) != 0) {
00212 if(ret != DB_NOTFOUND) cf_log(LOG_ERR,__FILE__,__LINE__,"ALERT! DB->del failed: %s\n",db_strerror(ret));
00213 }
00214 }
00215 }
00216 else {
00217 cf_log(LOG_ERR,__FILE__,__LINE__,"DB->get: %s\n",db_strerror(ret));
00218 writen(connfd,"504 Auth required\n",18);
00219 }
00220 }
00221 }
00222 else {
00223 writen(connfd,"504 Auth required\n",18);
00224 }
00225 }
00226 else {
00227
00228 key.data = names[1];
00229 key.size = strlen(names[1]);
00230
00231 if((ret = NamesDB->get(NamesDB,NULL,&key,&data,0)) == 0) {
00232 writen(connfd,"504 Auth required\n",18);
00233 }
00234 else {
00235 if(ret == DB_NOTFOUND) {
00236 data.data = pass;
00237 data.size = strlen(pass)+1;
00238 if((ret = NamesDB->put(NamesDB,NULL,&key,&data,0)) != 0) {
00239 cf_log(LOG_ERR,__FILE__,__LINE__,"DB->put: %s\n",db_strerror(ret));
00240 writen(connfd,"504 Auth required\n",18);
00241 }
00242 else {
00243 writen(connfd,"200 Ok\n",7);
00244 }
00245 }
00246 else {
00247 cf_log(LOG_ERR,__FILE__,__LINE__,"DB->get: %s\n",db_strerror(ret));
00248 writen(connfd,"504 Auth required\n",18);
00249 }
00250 }
00251 }
00252 }
00253
00254 }
00255 else {
00256 writen(connfd,"503 Sorry, I do not understand\n",31);
00257 }
00258 }
00259 else {
00260 writen(connfd,"503 Sorry, I do not understand\n",31);
00261 }
00262
00263 free(ln);
00264 }
00265
00266 if(infos) cf_hash_destroy(infos);
00267
00268 return FLT_OK;
00269 }
00270
00271 return FLT_DECLINE;
00272 }
00273
00274 int flt_registerednames_init_module(int sock) {
00275 int ret;
00276
00277 if(!AuthNames) {
00278 cf_log(LOG_ERR,__FILE__,__LINE__,"I need a database to save the names in!\n");
00279 return FLT_EXIT;
00280 }
00281
00282 if((ret = db_create(&NamesDB,NULL,0)) != 0) {
00283 cf_log(LOG_ERR,__FILE__,__LINE__,"db_create: %s\n",db_strerror(ret));
00284 return FLT_EXIT;
00285 }
00286
00287 if((ret = NamesDB->open(NamesDB,AuthNames,NULL,DB_HASH,DB_CREATE,0644)) != 0) {
00288 cf_log(LOG_ERR,__FILE__,__LINE__,"DB->open: %s\n",db_strerror(ret));
00289 return FLT_EXIT;
00290 }
00291
00292 cf_register_protocol_handler("AUTH",flt_registerednames_handler);
00293
00294 return FLT_OK;
00295 }
00296
00297 int flt_registerednames_handle_command(t_configfile *cf,t_conf_opt *opt,u_char **args,int argnum) {
00298 if(argnum == 1) {
00299 if(AuthNames) free(AuthNames);
00300 AuthNames = strdup(args[0]);
00301 }
00302 else {
00303 cf_log(LOG_ERR,__FILE__,__LINE__,"flt_registerednames: expecting one argument for directive AuthNames!\n");
00304 }
00305
00306 return 0;
00307 }
00308
00309 void flt_registerednames_cleanup(void) {
00310 if(AuthNames) free(AuthNames);
00311 if(NamesDB) NamesDB->close(NamesDB,0);
00312 }
00313
00314 t_conf_opt flt_registerednames_config[] = {
00315 { "AuthNames", flt_registerednames_handle_command, NULL },
00316 { NULL, NULL, NULL }
00317 };
00318
00319 t_handler_config flt_registerednames_handlers[] = {
00320 { INIT_HANDLER, flt_registerednames_init_module },
00321 { 0, NULL }
00322 };
00323
00324 t_module_config flt_registerednames = {
00325 flt_registerednames_config,
00326 flt_registerednames_handlers,
00327 NULL,
00328 NULL,
00329 NULL,
00330 flt_registerednames_cleanup
00331 };
00332
00333