static SLang_BString_Type * concat_bstrings (SLang_BString_Type *a, SLang_BString_Type *b) { unsigned int len; SLang_BString_Type *c; char *bytes; len = a->len + b->len; #if SLANG_USE_TMP_OPTIMIZATION if ((a->num_refs == 1) /* owned by stack */ && (a->ptr_type == IS_BSTRING) && (len <= a->malloced_len)) { bytes = (char *)a->v.bytes; memcpy (bytes + a->len, (char *)BS_GET_POINTER(b), b->len); bytes[len] = 0; /* ok to \0 terminate --- see above */ a->len = len; a->num_refs++; return a; } #endif if (NULL == (c = SLbstring_create (NULL, len))) return NULL; bytes = (char *)BS_GET_POINTER(c); memcpy (bytes, (char *)BS_GET_POINTER(a), a->len); memcpy (bytes + a->len, (char *)BS_GET_POINTER(b), b->len); bytes[len] = 0; return c; }
static void sl_base64_decode (void){ char* input, *in; BIO* bmem,* b64; SLang_BString_Type* output; int i, outlen; char nl[]="\n"; if (SLang_Num_Function_Args != 1 || SLang_pop_slstring(&in) == -1 ){ return; } /* For some reason, the input is required to have a newline at the end, doesn't matter how many, so tack one on here*/ input = SLang_concat_slstrings(in,nl); SLang_free_slstring(in); unsigned char* buff = (char*)malloc((int)strlen(input)+1); memset(buff,0,(int)strlen(input)); b64 = BIO_new(BIO_f_base64()); bmem = BIO_new_mem_buf(input,(int)strlen(input)); bmem = BIO_push(b64,bmem); outlen = BIO_read(bmem,buff,(int)strlen(input)); BIO_free_all(bmem); output = SLbstring_create(buff, outlen); SLang_push_bstring(output); SLang_free_slstring(input); SLbstring_free(output); free(buff); }
static void sl_ssl_read(void){ SLssl_Type *ssl; SLang_MMT_Type *sslmmt; SLang_Ref_Type *buff; void *ibuff; SLang_BString_Type *data; int r, rlen; if (SLang_pop_integer(&rlen)==-1 || SLang_pop_ref(&buff)==-1 || NULL==(sslmmt=SLang_pop_mmt(SLssl_Type_Id))) return; ssl=(SLssl_Type *)SLang_object_from_mmt(sslmmt); ibuff=(void *)malloc(rlen); r=SSL_read((SSL *)ssl->ssl,ibuff,rlen); data=SLbstring_create((unsigned char *)ibuff,r); SLang_assign_to_ref(buff, SLANG_BSTRING_TYPE, (VOID_STAR)&data); if (r>=0) SLang_push_integer(r); else SLang_verror(r,"SSL read returned error code %d", SSL_get_error((SSL *)ssl->ssl,r)); SLang_free_ref(buff); }
static void sl_decrypt (void){ /* input types */ char *ctype; unsigned char *outbuf, *iiv, *ikey, *idata; SLang_BString_Type *iv, *key, *data; /* internal types */ EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher; int outlen, tmplen, dlen, i; /* output types */ SLang_BString_Type *output; if (SLang_Num_Function_Args != 4 || SLang_pop_slstring(&ctype) == -1 ){ return; } cipher = EVP_get_cipherbyname(ctype); if (!cipher){ SLang_verror(SL_UNDEFINED_NAME,"could not find cipher %s",ctype); return; } if (SLang_pop_bstring(&iv) == -1 || SLang_pop_bstring(&key) == -1 || SLang_pop_bstring(&data) == -1 ){ return; } iiv = SLbstring_get_pointer (iv,&i); ikey = SLbstring_get_pointer (key,&i); idata = SLbstring_get_pointer (data,&dlen); outbuf = (char*)malloc(dlen+EVP_CIPHER_block_size(cipher)); EVP_CIPHER_CTX_init(&ctx); EVP_DecryptInit_ex(&ctx, cipher, NULL, ikey, iiv); if (!EVP_DecryptUpdate(&ctx, outbuf, &outlen, idata, dlen)){ return; /*emit an error here*/ } if (!EVP_DecryptFinal(&ctx, outbuf + outlen, &tmplen)){ return; /*emit an error here*/ } outlen+=tmplen; output = SLbstring_create (outbuf, outlen); SLang_push_bstring(output); SLbstring_free(output); SLbstring_free(data); SLbstring_free(key); SLbstring_free(iv); free(outbuf); }
static SLang_BString_Type * concat_bstrings (SLang_BString_Type *a, SLang_BString_Type *b) { unsigned int len; SLang_BString_Type *c; char *bytes; len = a->len + b->len; if (NULL == (c = SLbstring_create (NULL, len))) return NULL; bytes = (char *)BS_GET_POINTER(c); memcpy (bytes, (char *)BS_GET_POINTER(a), a->len); memcpy (bytes + a->len, (char *)BS_GET_POINTER(b), b->len); return c; }
static void _iconv_reset_shift(ICONV_Type *it) { size_t n = SHIFT_BUF_LEN; char buf[SHIFT_BUF_LEN], *p = buf; SLang_BString_Type *bstr; size_t rc; rc = iconv(it->cd, NULL, NULL, &p, &n); if ((rc == (size_t)(-1)) || (n > rc)) { SLang_verror (SL_Internal_Error, "Internal error: shift buffer too small in iconv_reset_shift!"); return; } buf[SHIFT_BUF_LEN-n] = '\0'; bstr = SLbstring_create((unsigned char *)buf, SHIFT_BUF_LEN-n); if (bstr == NULL) return; (void) SLang_push_bstring(bstr); SLbstring_free (bstr); }
static void sl_ssl_get_cert(void){ SLssl_Type *ssl; SLang_MMT_Type *sslmmt; STACK_OF(X509) *cert; unsigned char **buf; SLang_BString_Type **certout; SLang_Array_Type *arr; SLindex_Type nelem; int len,i; if (NULL==(sslmmt=SLang_pop_mmt(SLssl_Type_Id))) return; ssl=(SLssl_Type *)SLang_object_from_mmt(sslmmt); cert=SSL_get_peer_cert_chain((SSL *)ssl->ssl); if (cert==NULL) return NULL; nelem=(SLindex_Type)sk_X509_num(cert); // now we have chain of certs, create array of pointers and the // array to hold them buf = (unsigned char **)malloc(nelem*sizeof(unsigned char *)); arr = SLang_create_array(SLANG_BSTRING_TYPE,0,NULL,&nelem,1); // array data structure is of bstring type certout = (SLang_BString_Type **)arr->data; for (i=0;i<nelem;i++){ buf[i] = NULL; len = i2d_X509(sk_X509_value(cert,i), &(buf[i])); certout[i] = SLbstring_create(buf[i],len); } SLang_push_array(arr,1); // free the X509 stack sk_X509_pop_free(cert,X509_free); }
static void sl_hmac (void){ char *dtype; SLang_BString_Type *key, *data; unsigned char *ikey, *idata; unsigned char hash[EVP_MAX_MD_SIZE]; unsigned int hashlen, klen, dlen; SLang_BString_Type *output; const EVP_MD *md; if (SLang_Num_Function_Args != 3 || SLang_pop_slstring(&dtype) == -1 ){ return; } /* should return error there of course */ md=EVP_get_digestbyname(dtype); if (!md){ SLang_verror(SL_UNDEFINED_NAME,"could not find digest %s",dtype); SLang_free_slstring(dtype); return; } if (SLang_pop_bstring(&key) == -1 || SLang_pop_bstring(&data) == -1 ){ return; } ikey = SLbstring_get_pointer(key, &klen); idata = SLbstring_get_pointer(data, &dlen); HMAC(md,ikey,klen,idata,dlen,&hash,&hashlen); output = SLbstring_create(hash, hashlen); SLang_push_bstring(output); SLbstring_free(data); SLbstring_free(key); SLbstring_free(output); SLang_free_slstring(dtype); }
static void sl_digest (void){ SLang_BString_Type* data; /* we will give a slang string */ unsigned char output[EVP_MAX_MD_SIZE]; const EVP_MD *md; EVP_MD_CTX ctx; char* dtype; int dlen, hashlen; SLang_BString_Type *out; if (SLang_Num_Function_Args != 2 || SLang_pop_slstring(&dtype) == -1 ){ return;} md = EVP_get_digestbyname(dtype); if (!md){ SLang_verror(SL_UNDEFINED_NAME,"could not find digest %s",dtype); SLang_free_slstring(dtype); return; } if (SLang_pop_bstring(&data) == -1 ){ return; } unsigned char* idata = SLbstring_get_pointer (data,&dlen); EVP_MD_CTX_init(&ctx); EVP_DigestInit_ex(&ctx, md, NULL); EVP_DigestUpdate(&ctx, idata, dlen); EVP_DigestFinal(&ctx, output, &hashlen); out = SLbstring_create (output, hashlen); SLang_push_bstring(out); SLbstring_free(data); SLbstring_free(out); }
static void _iconv(ICONV_Type *it, SLang_BString_Type *bstr) { char *buf = NULL; size_t rc; char ICONV_CONST *instr; char *outstr; size_t inn, outn, bufn; size_t fail = (size_t)-1; SLstrlen_Type bstrlen; if (NULL == (instr = (char ICONV_CONST *)SLbstring_get_pointer(bstr, &bstrlen))) return; inn = (size_t) bstrlen; bufn = outn = 2*inn + 2; if (NULL == (buf = (char *)SLmalloc(bufn))) return; outstr = buf; while (1) { errno = 0; rc = iconv(it->cd, &instr, &inn, &outstr, &outn); if (rc != (size_t)-1) break; /* ok! */ if (fail == inn) { SLang_verror (SL_Unknown_Error, "Unknown error in iconv"); goto error; } fail = inn; switch (errno) { case EILSEQ: SLang_verror (SL_InvalidUTF8_Error, "Invalid multibyte sequence or unable to convert to the target encoding"); goto error; case EINVAL: SLang_verror (SL_InvalidUTF8_Error, "Incomplete multibyte sequence"); goto error; case 0: /* drop */ /* grrrr * At least on windows, libiconv returns with errno = 0 * (or unmodified?) when there's no more roon on outstr * if so, fallback */ case E2BIG: { char *p; long outdelta; outdelta = outstr - buf; outn += bufn; bufn += bufn; p = (char *)SLrealloc(buf, bufn); if (p == NULL) goto error; buf = p; outstr = buf + outdelta; } break; default: SLang_verror (SL_Unknown_Error, "Unknown iconv error"); goto error; } } bstr = SLbstring_create((unsigned char *) buf, outstr - buf); if (bstr != NULL) (void) SLang_push_bstring(bstr); SLbstring_free (bstr); /* drop */ error: SLfree(buf); }
static void sl_generate_key (void){ char* pass, *ctype, *dtype; SLang_BString_Type* salta; const EVP_CIPHER *cipher; const EVP_MD *md; unsigned char *salt; unsigned char *key; unsigned char *iv; SLang_BString_Type* outkey, *outiv; int count,i,keylen,ivlen,saltlen; if (SLang_Num_Function_Args != 5 || SLang_pop_slstring(&dtype) == -1 || SLang_pop_slstring(&ctype) == -1 ){ return; } cipher = EVP_get_cipherbyname(ctype); if (!cipher){ SLang_verror(SL_UNDEFINED_NAME,"could not find cipher %s",ctype); SLang_free_slstring(ctype); return; } md = EVP_get_digestbyname(dtype); if (!md){ SLang_verror(SL_UNDEFINED_NAME,"could not find digest %s",dtype); SLang_free_slstring(ctype); SLang_free_slstring(dtype); return; } if (SLang_pop_integer(&count) == -1 || SLang_pop_bstring(&salta) == -1 || SLang_pop_slstring(&pass) == -1 ){ return; } keylen = EVP_CIPHER_key_length(cipher); ivlen = EVP_CIPHER_iv_length(cipher); key = (char*)malloc(keylen); iv = (char*)malloc(ivlen); salt = SLbstring_get_pointer(salta,&saltlen); if (saltlen==0){ salt=NULL; } else if (saltlen!=8){ SLang_verror(SL_USAGE_ERROR,"Salt must not exceed 8 bytes"); SLbstring_free(salta); SLang_free_slstring(pass); SLang_free_slstring(ctype); SLang_free_slstring(dtype); return; } EVP_BytesToKey(cipher,md,salt,pass,(int)strlen(pass),count,key,iv); outkey = SLbstring_create(key, keylen); outiv = SLbstring_create(iv, ivlen); SLang_push_bstring(outkey); SLang_push_bstring(outiv); SLbstring_free(salta); SLbstring_free(outkey); SLbstring_free(outiv); SLang_free_slstring(pass); SLang_free_slstring(ctype); SLang_free_slstring(dtype); free(key);free(iv); }