📄 cspace_validator.c
字号:
#include <openssl/ssl.h>#include "mod_cspace_defines.h"#include "cspace_validator.h"/*#ifdef CSPACE_APACHE2*/#include "apr_dso.h"#include "apr_file_info.h"/*#endif*//* In validating the saml token using xmlsec we anyway need the CA cert * of the CA which signed the IdP's cert. Hence, the "promiscuous" and "cert" * validators are the same (does nothing infact) in this module. Yet we include * both these types for completeness. */ typedef enum { VAL_TYPE_WHITE = 0, VAL_TYPE_BLACK, VAL_TYPE_CERT, VAL_TYPE_PROMISCUOUS, VAL_TYPE_USER, VAL_TYPE_FAULT = -1} val_type;char *(val_name[5]) = {"white", "black", "cert", "promiscuous", "user"};static int white_list_validator(const char *uri, const char *issuer, const char *ppid, const char *cert, const char *w_list);static int black_list_validator(const char *uri, const char *issuer, const char *ppid, const char *cert, const char *b_list);static int cert_validator(const char *uri, const char *issuer, const char *ppid, const char *cert, const void *data);static int user_validator(const char *uri, const char *issuer, const char *ppid, const char *cert, const char *dso_fname, void *cb_data, void *data);static val_type valstr2type(const char *validator);static X509 *x509_create_with_buffer(unsigned char *input, int length);static X509 *x509_create_with_buffer(unsigned char *input, int length){ BIO *b64, *bmem; X509 *x509 = NULL; char *buffer = NULL; /*TODO: replace mallocs with apr_palloc when used with apache*/ buffer = (char *)malloc(length); memset(buffer, 0, length); b64 = BIO_new(BIO_f_base64()); BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); bmem = BIO_new_mem_buf(input, length); bmem = BIO_push(b64, bmem); x509 = d2i_X509_bio(bmem, NULL); BIO_free_all(bmem); free(buffer); return x509;}#define MAXARR 1024#define ISSUER_SELF "http://schemas.xmlsoap.org/ws/2005/05/identity/issuer/self"static int white_list_validator(const char *uri, const char *issuer, const char *ppid, const char *cert, const char *w_list){ FILE *fp = NULL; X509 *needle = NULL; X509 *(haystack[MAXARR]); /* TODO: this list should be made static */ int i = 0, j = 0; if (issuer && strcmp(issuer, ISSUER_SELF) == 0) { return FAIL; } if (cert) { needle = x509_create_with_buffer((void *)cert, strlen(cert)); } /*ideally we would read this file only once per server init*/ i=0; if ((fp = fopen (w_list, "r"))) { while (!feof(fp)) { if (i < MAXARR) { haystack[i++] = PEM_read_X509(fp, NULL, NULL, NULL); } else { break; } } } else { return FAIL; } for (j=0; j<i; j++) { if (haystack[j] && (M_ASN1_BIT_STRING_cmp(haystack[j]->signature, needle->signature) == 0)) { if (needle) { X509_free(needle); } /* free the haystack */ for (j=0; j<i; j++) { if (haystack[j]) { X509_free(haystack[j]); } } fclose(fp); return SUCC; } } if (needle) { X509_free(needle); } /* free the haystack */ for (j=0; j<i; j++) { if (haystack[j]) { X509_free(haystack[j]); } } fclose(fp); return FAIL;}#define MAX_HOST_NAME_LEN 1024static int black_list_validator(const char *uri, const char *issuer, const char *ppid, const char *cert, const char *b_list){ char line[MAX_HOST_NAME_LEN]; FILE *fp = NULL; X509 *crt= NULL; char *cn = NULL; if (cert) { crt = x509_create_with_buffer((void *)cert, strlen(cert)); } if ((fp = fopen(b_list, "r"))) { while (fgets(line, MAX_HOST_NAME_LEN, fp) != NULL) { if (strstr(line, cn)) { fclose(fp); return FAIL; } } } else { return FAIL; } fclose(fp); /*if not found in black list allow it*/ return SUCC;}static int cert_validator(const char *uri, const char *issuer, const char *ppid, const char *cert, const void *data){ /* this validation is done at the cert verification */ return SUCC;}/* Allow all the requests in case of promiscuous */#define promiscuous_validator(a, b, c, d, e) SUCC/*TODO: cb_user data should be requested from the user using an init() callback*/static int user_validator(const char *uri, const char *issuer, const char *ppid, const char *cert, const char *dso_fname, void *cb_data, void *ctx) {/*#ifdef CSPACE_APACHE2*/ apr_status_t rv; apr_dso_handle_sym_t sym = NULL; apr_dso_handle_t *hand = NULL; char *fname = NULL; apr_pool_t *p = (apr_pool_t *) ctx; cspace_user_validator_cb_t func; if (!ppid || !dso_fname) return FAIL; apr_filepath_merge(&fname, NULL, dso_fname, 0, p); rv = apr_dso_load(&hand, dso_fname, p); if (rv) { /*read error using: apr_dso_error(hand, char [128], 128)*/ /*log error*/ apr_dso_unload(hand); return FAIL; } rv = apr_dso_sym(&sym, hand, "cspace_user_validate"); if (rv) { /*read error using: apr_dso_error(hand, char [128], 128)*/ /*log error*/ apr_dso_unload(hand); return FAIL; } /*is it meaningful to do a if(func)?*/ func = (cspace_user_validator_cb_t)sym; rv = (*func)(uri, issuer, ppid, cert, cb_data); apr_dso_unload(hand); return rv;/*#else return FAIL;#endif*/}static val_type valstr2type(const char *validator){ if (strcmp(validator, val_name[VAL_TYPE_WHITE]) == 0) { return VAL_TYPE_WHITE; } else if (strcmp(validator, val_name[VAL_TYPE_BLACK]) == 0) { return VAL_TYPE_BLACK; } else if (strcmp(validator, val_name[VAL_TYPE_CERT]) == 0) { return VAL_TYPE_CERT; } else if (strcmp(validator, val_name[VAL_TYPE_PROMISCUOUS]) == 0) { return VAL_TYPE_PROMISCUOUS; } else { return VAL_TYPE_FAULT; }}int validate_with_op_mode(const char *validator, const char *uri, const char *issuer, const char *ppid, const char *cert, const void *val_data, void *ctx){ int flag = FAIL; val_type v_type = valstr2type(validator); switch (v_type) { case VAL_TYPE_WHITE: flag = white_list_validator(uri, issuer, NULL, cert, val_data); break; case VAL_TYPE_BLACK: flag = black_list_validator(uri, issuer, NULL, cert, val_data); break; case VAL_TYPE_CERT: flag = cert_validator(uri, NULL, NULL, cert, NULL); break; case VAL_TYPE_USER: flag = user_validator(uri, issuer, ppid, cert, (char *)val_data, NULL, ctx); break; case VAL_TYPE_PROMISCUOUS: flag = promiscuous_validator(NULL, NULL, NULL, NULL, NULL); break; default: flag = FAIL; } return flag;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -