⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl_client.c

📁 cas 客户端文件
💻 C
字号:
/*  * OpenSSL-based CAS ticket validator by Shawn Bayern, based on  * OpenSSL demonstration code. */#include <stdio.h>#include <memory.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <openssl/crypto.h>#include <openssl/x509.h>#include <openssl/pem.h>#include <openssl/ssl.h>#include <openssl/err.h>#include "cas.h"#define END(x) { ret = (x); goto end; }#define FAIL END(0)#define FAIL_BAD_CERT END(BAD_CERT)#define SUCCEED END(1)/* * TODO: This really ought to be configurable at runtime.  At least you * can declare multiple CA certificates easily (at compile time) through * this array. */static char *trusted_ca[] = {    "/usr/local/etc/verisignserverca.pem",    NULL};int CAS_validate(char *ticket, char *service, char *outbuf, int outbuflen);static X509 *get_cert_from_file(char *filename);static int valid_cert(X509 *cert, char *hostname);/** Returns status of certification:  0 for invalid, 1 for valid. */static int valid_cert(X509 *cert, char *hostname){  int i;  char buf[4096];  X509_STORE *store = X509_STORE_new();  X509_STORE_CTX *ctx = X509_STORE_CTX_new();  for (i = 0; trusted_ca[i] != NULL; i++) {    X509 *cacert = get_cert_from_file(trusted_ca[i]);    if (cacert)      X509_STORE_add_cert(store, cacert);  }  X509_STORE_CTX_init(ctx, store, cert, sk_X509_new_null());  if (X509_verify_cert(ctx) == 0)    return 0;  X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName,    buf, sizeof(buf) - 1);  // anal-retentive:  make sure the hostname isn't as long as the  // buffer, since we don't want to match only because of truncation  if (strlen(hostname) >= sizeof(buf) - 1)    return 0;  return (!strcmp(buf, hostname));}/** Returns status of ticket by filling 'buf' with a NetID if the ticket *  is valid and buf is large enough and returning 1.  If not, 0 is *  returned. */int CAS_validate(char *ticket, char *service, char *outbuf, int outbuflen){  int err, b, ret, total;  int s = 0;  struct sockaddr_in sa;  struct hostent h, *hp2;  SSL_CTX *ctx = NULL;  SSL *ssl = NULL;  X509 *s_cert = NULL;  char buf[4096];  SSL_METHOD *method;  char *full_request, *str, *tmp;  SSLeay_add_ssl_algorithms();  method = SSLv23_client_method();  SSL_load_error_strings();  ctx = SSL_CTX_new(method);  if (!ctx)    FAIL;  if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)    FAIL;  memset(&sa, 0, sizeof(sa));  sa.sin_family = AF_INET;  hp2 = gethostbyname(CAS_HOST);  memcpy(&h, hp2, sizeof(h));//  gethostbyname_r(CAS_HOST, &h, buf, sizeof(buf), &hp2, &b);  memcpy(&(sa.sin_addr.s_addr), h.h_addr_list[0], sizeof(long));  sa.sin_port = htons(CAS_PORT);  if (connect(s, (struct sockaddr*) &sa, sizeof(sa)) == -1)    FAIL;  if (!(ssl = SSL_new(ctx)))    FAIL;  SSL_set_fd(ssl, s);  if (!SSL_connect(ssl))    FAIL;  if (!(s_cert = SSL_get_peer_certificate(ssl)))    FAIL_BAD_CERT;  if (!valid_cert(s_cert, CAS_HOST))    FAIL_BAD_CERT;  X509_free(s_cert);  full_request = malloc(strlen(CAS_METHOD) + strlen(" ")    + strlen(CAS_VALIDATE) + strlen("?ticket=") + strlen(ticket) +     + strlen("&service=") + strlen(service) + strlen(" ")     + strlen(CAS_PROT) + strlen("\n\n") + 1);  sprintf(full_request, "%s %s?ticket=%s&service=%s %s\n\n",    CAS_METHOD, CAS_VALIDATE, ticket, service, CAS_PROT);  if (!SSL_write(ssl, full_request, strlen(full_request)))    FAIL;  total = 0;  do {    b = SSL_read(ssl, buf + total, (sizeof(buf) - 1) - total);    total += b;  } while (b > 0);  buf[total] = '\0';  if (b != 0 || total >= sizeof(buf) - 1)    FAIL;		// unexpected read error or response too large  /*   * The following segment of code is spelled out in excruciating detail   * since it's worth the extra care.   */  str = strstr(buf, "\r\n\r\n");  // find the end of the header  if (!str)    FAIL;			// no header  str += 4;			// safe because we just found "\r\n\r\n"  if (strncmp(str, "yes", 3))    FAIL;			// no affirmative response  str = strchr(str, '\n');	// find the end of the current line  if (!str) {    str = strchr(str, '\r');    // possibly ended in CR (ok by RFC-2616)    if (!str)      FAIL;			// unexpectedly short body  }  str++;			// safe because we just found "\n" or "\r"    // now, we've got the NetID and a bunch of crap after it.  Find the next  // '[\r]\n' and end the string there  {    char *str2 = strchr(str, '\r');    if (!str2) {      str2 = strchr(str, '\n');	if (!str2)	  FAIL;			// unexpectedly short body    }    *str2 = '\0';		// remove [\r]\n  }  /*   * without enough space, fail entirely, since a partial NetID could   * be dangerous   */  if (outbuflen < strlen(str) + 1)    FAIL;  strcpy(outbuf, str);  SUCCEED;   /* cleanup and return */end:  if (ssl)    SSL_shutdown(ssl);  if (s > 0)    close(s);  if (ssl)    SSL_free(ssl);  if (ctx)    SSL_CTX_free(ctx);  return ret;}static X509 *get_cert_from_file(char *filename) {    FILE *f = fopen(filename, "r");    if (f) {	X509 *c = PEM_read_X509(f, NULL, NULL, NULL);	fclose(f);	return c;    } else {	return NULL;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -