00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00030 #include <stdio.h>
00031 #include <time.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034
00035 #include <openssl/pem.h>
00036 #include <openssl/err.h>
00037 #include <openssl/sha.h>
00038
00039 #include "../../mem/shm_mem.h"
00040 #include "../../hashes.h"
00041 #include "auth_identity.h"
00042
00043 #define lock_element(_cell) lock_get(&((_cell)->lock))
00044 #define release_element(_cell) lock_release(&((_cell)->lock))
00045
00046 static int insert_into_table(ttable *ptable, void *pdata, unsigned int uhash);
00047 static void remove_from_table_unsafe(ttable *ptable, titem *pitem);
00048 static void remove_least(ttable *ptable, unsigned int uhash);
00049 static void* search_item_in_table_unsafe(ttable *ptable,
00050 const void *pneedle,
00051 unsigned int uhash);
00052
00053 time_t glb_tnow=0;
00054
00055
00056 int init_table(ttable **ptable,
00057 unsigned int ubucknum,
00058 unsigned int uitemlim,
00059 table_item_cmp *fcmp,
00060 table_item_searchinit *fsinit,
00061 table_item_cmp *fleast,
00062
00063 table_item_free *ffree,
00064 table_item_gc *fgc)
00065 {
00066 int i1;
00067
00068 if (!(*ptable = (ttable *) shm_malloc(sizeof(**ptable)))) {
00069 LOG(L_ERR, "AUTH_IDENTITY:init_table: Not enough shared memory error\n");
00070 return -1;
00071 }
00072 memset(*ptable, 0, sizeof(**ptable));
00073
00074 if (!((*ptable)->entries = (tbucket *) shm_malloc(sizeof(tbucket)*ubucknum))) {
00075 LOG(L_ERR, "AUTH_IDENTITY:init_table: Not enough shared memory error\n");
00076 return -1;
00077 }
00078 memset((*ptable)->entries, 0, sizeof(tbucket)*ubucknum);
00079 for (i1=0; i1<ubucknum; i1++) {
00080 (*ptable)->entries[i1].pfirst = NULL;
00081 lock_init(&(*ptable)->entries[i1].lock);
00082 }
00083
00084 (*ptable)->uitemlim=uitemlim;
00085 (*ptable)->ubuckets=ubucknum;
00086
00087 (*ptable)->fcmp=fcmp;
00088 (*ptable)->fsearchinit=fsinit;
00089 (*ptable)->fleast=fleast;
00090 (*ptable)->ffree=ffree;
00091 (*ptable)->fgc=fgc;
00092
00093 return 0;
00094 }
00095
00096 void free_table(ttable *ptable)
00097 {
00098 unsigned int u1;
00099 titem *pitem, *previtem;
00100
00101 if (ptable) {
00102 for (u1=0; u1 < ptable->ubuckets; u1++)
00103 {
00104 pitem=ptable->entries[u1].pfirst;
00105 while (pitem) {
00106 previtem=pitem;
00107 pitem=pitem->pnext;
00108
00109 ptable->ffree(previtem->pdata);
00110 shm_free(previtem);
00111 }
00112 }
00113 shm_free(ptable->entries);
00114 shm_free(ptable);
00115 }
00116 }
00117
00118
00119 static int insert_into_table(ttable *ptable, void *pdata, unsigned int uhash)
00120 {
00121 tbucket *pbucket;
00122 titem *pitem;
00123 char bneed2remove=0;
00124
00125 if (!(pitem=(titem *)shm_malloc(sizeof(*pitem)))) {
00126 LOG(L_ERR, "AUTH_IDENTITY:insert_into_table: Not enough shared memory error\n");
00127 return -1;
00128 }
00129
00130 memset(pitem, 0, sizeof(*pitem));
00131 pitem->uhash=uhash;
00132 pitem->pdata=pdata;
00133
00134 lock_element(ptable);
00135
00136 if (ptable->unum >= ptable->uitemlim)
00137 bneed2remove=1;
00138 ptable->unum++;
00139 release_element(ptable);
00140
00141 if (bneed2remove)
00142 remove_least(ptable, uhash);
00143
00144
00145 pbucket = &ptable->entries[uhash];
00146
00147
00148 lock_element(pbucket);
00149 if (pbucket->plast) {
00150 pbucket->plast->pnext = pitem;
00151 pitem->pprev = pbucket->plast;
00152 } else pbucket->pfirst = pitem;
00153 pbucket->plast = pitem;
00154 release_element(pbucket);
00155
00156 return 0;
00157 }
00158
00159
00160
00161 static void remove_from_table_unsafe(ttable *ptable, titem *pitem)
00162 {
00163 tbucket *pbucket = &(ptable->entries[pitem->uhash]);
00164
00165
00166 if (pitem->pprev)
00167 pitem->pprev->pnext = pitem->pnext;
00168 else
00169 pbucket->pfirst = pitem->pnext;
00170
00171 if (pitem->pnext)
00172 pitem->pnext->pprev = pitem->pprev;
00173 else
00174 pbucket->plast = pitem->pprev;
00175
00176 if (ptable->ffree)
00177 ptable->ffree(pitem->pdata);
00178
00179 shm_free(pitem);
00180 }
00181
00182
00183
00184 static void remove_least(ttable *ptable, unsigned int uhash)
00185 {
00186 tbucket *pbucket;
00187 unsigned int u1, uhashnow;
00188 titem *pleastitem=NULL, *pnow;
00189 int ires;
00190
00191 if (!ptable->fleast)
00192 return ;
00193 if (ptable->fsearchinit)
00194 ptable->fsearchinit();
00195
00196 for (uhashnow=uhash,u1=0, pbucket=&(ptable->entries[uhash]);
00197 u1 < ptable->ubuckets;
00198 u1++,pbucket=&(ptable->entries[uhashnow])) {
00199
00200 lock_element(pbucket);
00201
00202 for (pnow=pbucket->pfirst;pnow;pnow=pnow->pnext) {
00203 if (!pleastitem) {
00204 pleastitem=pnow;
00205 continue;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 ires=ptable->fleast(pleastitem->pdata, pnow->pdata);
00217 if (ires==1)
00218 pleastitem=pnow;
00219 if (ires==-2)
00220 break;
00221 if (ires==-3) {
00222 pleastitem=pnow;
00223 break;
00224 }
00225 }
00226
00227 if (pleastitem) {
00228
00229 lock_element(ptable);
00230 ptable->unum--;
00231 release_element(ptable);
00232
00233 remove_from_table_unsafe(ptable, pleastitem);
00234 release_element(pbucket);
00235 return ;
00236 }
00237 release_element(pbucket);
00238
00239
00240
00241 if (uhashnow + 1 == ptable->ubuckets)
00242 uhashnow=0;
00243 else
00244
00245 uhashnow++;
00246 }
00247 }
00248
00249
00250 static void* search_item_in_table_unsafe(ttable *ptable,
00251 const void *pneedle,
00252 unsigned int uhash)
00253 {
00254 tbucket *pbucket = &(ptable->entries[uhash]);
00255 titem *pnow;
00256 void *pret=NULL;
00257
00258 if (!ptable->fcmp)
00259 return NULL;
00260
00261 for (pnow=pbucket->pfirst;pnow;pnow=pnow->pnext) {
00262 if (!ptable->fcmp(pneedle, pnow->pdata)) {
00263 pret=pnow->pdata;
00264 break;
00265 }
00266 }
00267
00268 return pret;
00269 }
00270
00271
00272 void garbage_collect(ttable *ptable, int ihashstart, int ihashend)
00273 {
00274 unsigned int unum, uremoved;
00275 int i1;
00276 tbucket *pbucket;
00277 titem *pnow;
00278
00279
00280
00281 if (!ptable->fgc)
00282 return;
00283
00284 if (ptable->fsearchinit)
00285 ptable->fsearchinit();
00286
00287 lock_element(ptable);
00288 unum=ptable->unum;
00289 release_element(ptable);
00290
00291
00292
00293
00294
00295 if (!unum)
00296 return ;
00297
00298 for (i1=ihashstart; i1<=ihashend; i1++) {
00299 uremoved=0;
00300 pbucket=&(ptable->entries[i1]);
00301
00302 lock_element(pbucket);
00303 for (pnow=pbucket->pfirst;pnow;pnow=pnow->pnext) {
00304 if (ptable->fgc(pnow->pdata)) {
00305 remove_from_table_unsafe(ptable, pnow);
00306 uremoved++;
00307 }
00308 }
00309
00310 if (uremoved) {
00311 lock_element(ptable);
00312 ptable->unum-=uremoved;
00313 release_element(ptable);
00314 }
00315 release_element(pbucket);
00316 }
00317 }
00318
00319
00320
00321
00322
00323 static int str_duplicate(str* _d, str* _s)
00324 {
00325
00326 _d->s = (char *)shm_malloc(sizeof(char)*(_s->len));
00327 if (!_d->s) {
00328 LOG(L_ERR, "AUTH_IDENTITY:str_duplicate: No enough shared memory\n");
00329 return -1;
00330 }
00331
00332 memcpy(_d->s, _s->s, _s->len);
00333 _d->len = _s->len;
00334 return 0;
00335 }
00336
00337
00338
00339
00340
00341
00342 int cert_item_cmp(const void *s1, const void *s2)
00343 {
00344 tcert_item *p1=(tcert_item*)s1, *p2=(tcert_item*)s2;
00345
00346 return !(p1->surl.len==p2->surl.len && !memcmp(p1->surl.s, p2->surl.s, p2->surl.len));
00347 }
00348
00349 void cert_item_init()
00350 {
00351
00352
00353 glb_tnow=time(0);
00354 }
00355
00356
00357 int cert_item_least(const void *s1, const void *s2)
00358 {
00359 if (((tcert_item *)s1)->ivalidbefore < glb_tnow)
00360 return -2;
00361 if (((tcert_item *)s2)->ivalidbefore < glb_tnow)
00362 return -3;
00363 return (((tcert_item *)s1)->uaccessed < ((tcert_item *)s2)->uaccessed) ? -1 : 1;
00364 }
00365
00366
00367 void cert_item_free(const void *sitem)
00368 {
00369 shm_free(((tcert_item *)sitem)->surl.s);
00370 shm_free(((tcert_item *)sitem)->scertpem.s);
00371 shm_free((tcert_item *)sitem);
00372 }
00373
00374
00375
00376 int get_cert_from_table(ttable *ptable, str *skey, tcert_item *ptarget)
00377 {
00378 tcert_item* tmp_tcert_item;
00379 unsigned int uhash;
00380 int iret=0;
00381
00382 uhash=get_hash1_raw(skey->s, skey->len) & (CERTIFICATE_TABLE_ENTRIES-1);
00383
00384
00385 lock_element(&ptable->entries[uhash]);
00386
00387 tmp_tcert_item = search_item_in_table_unsafe(ptable,
00388 (const void *)skey,
00389 uhash);
00390
00391
00392 if (tmp_tcert_item) {
00393 memcpy(ptarget->scertpem.s, tmp_tcert_item->scertpem.s, tmp_tcert_item->scertpem.len);
00394 ptarget->scertpem.len=tmp_tcert_item->scertpem.len;
00395
00396 tmp_tcert_item->uaccessed++;
00397 }
00398 else
00399 iret=1;
00400
00401 release_element(&ptable->entries[uhash]);
00402
00403 return iret;
00404 }
00405
00406
00407 int addcert2table(ttable *ptable, tcert_item *pcert)
00408 {
00409 tcert_item *pshmcert;
00410 unsigned int uhash;
00411
00412 if (!(pshmcert=(tcert_item *)shm_malloc(sizeof(*pshmcert)))) {
00413 LOG(L_ERR, "AUTH_IDENTITY:addcert2table: No enough shared memory\n");
00414 return -1;
00415 }
00416 memset(pshmcert, 0, sizeof(*pshmcert));
00417 if (str_duplicate(&pshmcert->surl, &pcert->surl))
00418 return -2;
00419
00420 if (str_duplicate(&pshmcert->scertpem, &pcert->scertpem))
00421 return -3;
00422
00423 pshmcert->ivalidbefore=pcert->ivalidbefore;
00424 pshmcert->uaccessed=1;
00425
00426 uhash=get_hash1_raw(pcert->surl.s, pcert->surl.len) & (CERTIFICATE_TABLE_ENTRIES-1);
00427
00428 if (insert_into_table(ptable, (void*)pshmcert, uhash))
00429 return -4;
00430
00431 return 0;
00432 }
00433
00434
00435
00436
00437
00438
00439
00440 int cid_item_cmp(const void *s1, const void *s2)
00441 {
00442 tcid_item *p1=(tcid_item*)s1, *p2=(tcid_item*)s2;
00443
00444 return !(p1->scid.len==p2->scid.len && !memcmp(p1->scid.s, p2->scid.s, p2->scid.len));
00445 }
00446
00447 void cid_item_init()
00448 {
00449 glb_tnow=time(0);
00450 }
00451
00452
00453 int cid_item_least(const void *s1, const void *s2)
00454 {
00455 if (((tcid_item *)s1)->ivalidbefore < glb_tnow)
00456 return -2;
00457 if (((tcid_item *)s2)->ivalidbefore < glb_tnow)
00458 return -3;
00459
00460 return (((tcid_item *)s1)->ivalidbefore < ((tcid_item *)s2)->ivalidbefore) ? -1 : 1;
00461 }
00462
00463
00464 int cid_item_gc(const void *s1)
00465 {
00466 return (((tcid_item *)s1)->ivalidbefore < glb_tnow);
00467 }
00468
00469
00470 void cid_item_free(const void *sitem)
00471 {
00472 tcid_item *pcid=(tcid_item *)sitem;
00473 tdlg_item *pdlgs, *pdlgs_next;
00474
00475 shm_free(pcid->scid.s);
00476
00477 pdlgs_next=pcid->pdlgs;
00478 while (pdlgs_next) {
00479 pdlgs=pdlgs_next;
00480 pdlgs_next=pdlgs_next->pnext;
00481 shm_free (pdlgs->sftag.s);
00482 shm_free (pdlgs);
00483 }
00484
00485 shm_free((tcert_item *)sitem);
00486 }
00487
00488
00489 int proc_cid(ttable *ptable,
00490 str *scid,
00491 str *sftag,
00492 unsigned int ucseq,
00493 time_t ivalidbefore)
00494 {
00495 tcid_item *pshmcid, *pcid_item;
00496 tdlg_item *pshmdlg, *pdlg_item, *pdlg_item_prev;
00497 unsigned int uhash;
00498
00499
00500
00501 if (!(pshmdlg=(tdlg_item *)shm_malloc(sizeof(*pshmdlg)))) {
00502 LOG(L_ERR, "AUTH_IDENTITY:addcid2table: No enough shared memory\n");
00503 return -1;
00504 }
00505 memset(pshmdlg, 0, sizeof(*pshmdlg));
00506 if (str_duplicate(&pshmdlg->sftag, sftag))
00507 return -2;
00508 pshmdlg->ucseq=ucseq;
00509
00510
00511
00512 uhash=get_hash1_raw(scid->s, scid->len) & (CALLID_TABLE_ENTRIES-1);
00513
00514 lock_element(&ptable->entries[uhash]);
00515
00516 pcid_item = search_item_in_table_unsafe(ptable,
00517 (const void *)scid,
00518 uhash);
00519
00520 if (pcid_item) {
00521 for (pdlg_item=pcid_item->pdlgs, pdlg_item_prev=NULL;
00522 pdlg_item;
00523 pdlg_item=pdlg_item->pnext) {
00524 if (pdlg_item->sftag.len==sftag->len
00525 && !memcmp(pdlg_item->sftag.s, sftag->s, sftag->len)) {
00526
00527 if (pdlg_item->ucseq>=ucseq) {
00528
00529
00530 release_element(&ptable->entries[uhash]);
00531
00532 shm_free(pshmdlg->sftag.s);
00533 shm_free(pshmdlg);
00534 return AUTH_FOUND;
00535 } else {
00536
00537
00538 pdlg_item->ucseq=ucseq;
00539 release_element(&ptable->entries[uhash]);
00540
00541 shm_free(pshmdlg->sftag.s);
00542 shm_free(pshmdlg);
00543 return 0;
00544 }
00545 }
00546
00547 pdlg_item_prev ?
00548 (pdlg_item_prev=pdlg_item_prev->pnext) :
00549 (pdlg_item_prev=pdlg_item);
00550 }
00551
00552 pdlg_item_prev->pnext=pshmdlg;
00553
00554
00555 pcid_item->ivalidbefore=ivalidbefore;
00556 }
00557
00558 release_element(&ptable->entries[uhash]);
00559
00560 if (!pcid_item) {
00561
00562 if (!(pshmcid=(tcid_item *)shm_malloc(sizeof(*pshmcid)))) {
00563 LOG(L_ERR, "AUTH_IDENTITY:addcid2table: No enough shared memory\n");
00564 return -4;
00565 }
00566 memset(pshmcid, 0, sizeof(*pshmcid));
00567 if (str_duplicate(&pshmcid->scid, scid)) {
00568 return -5;
00569 }
00570 pshmcid->ivalidbefore=ivalidbefore;
00571 pshmcid->pdlgs=pshmdlg;
00572 if (insert_into_table(ptable, (void*)pshmcid, uhash))
00573 return -6;
00574 }
00575
00576 return 0;
00577 }