/* iksemel (XML parser for Jabber)
** Copyright (C) 2000-2007 Gurer Ozen
** This code is free software; you can redistribute it and/or
** modify it under the terms of GNU Lesser General Public License.
*/
#include "common.h"
#include "iksemel.h"
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
#endif
#define SF_FOREIGN 1
#define SF_TRY_SECURE 2
#define SF_SECURE 4
struct stream_data {
iksparser *prs;
ikstack *s;
ikstransport *trans;
char *name_space;
void *user_data;
const char *server;
iksStreamHook *streamHook;
iksLogHook *logHook;
iks *current;
char *buf;
void *sock;
unsigned int flags;
char *auth_username;
char *auth_pass;
#ifdef HAVE_GNUTLS
gnutls_session sess;
gnutls_certificate_credentials cred;
#endif
};
#ifdef HAVE_GNUTLS
static size_t
tls_push (iksparser *prs, const char *buffer, size_t len)
{
struct stream_data *data = iks_user_data (prs);
int ret;
ret = data->trans->send (data->sock, buffer, len);
if (ret) return (size_t) -1;
return len;
}
static size_t
tls_pull (iksparser *prs, char *buffer, size_t len)
{
struct stream_data *data = iks_user_data (prs);
int ret;
ret = data->trans->recv (data->sock, buffer, len, -1);
if (ret == -1) return (size_t) -1;
return ret;
}
static int
handshake (struct stream_data *data)
{
const int protocol_priority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
const int kx_priority[] = { GNUTLS_KX_RSA, 0 };
const int cipher_priority[] = { GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0};
const int comp_priority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
const int mac_priority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
int ret;
if (gnutls_global_init () != 0)
return IKS_NOMEM;
if (gnutls_certificate_allocate_credentials (&data->cred) < 0)
return IKS_NOMEM;
if (gnutls_init (&data->sess, GNUTLS_CLIENT) != 0) {
gnutls_certificate_free_credentials (data->cred);
return IKS_NOMEM;
}
gnutls_protocol_set_priority (data->sess, protocol_priority);
gnutls_cipher_set_priority(data->sess, cipher_priority);
gnutls_compression_set_priority(data->sess, comp_priority);
gnutls_kx_set_priority(data->sess, kx_priority);
gnutls_mac_set_priority(data->sess, mac_priority);
gnutls_credentials_set (data->sess, GNUTLS_CRD_CERTIFICATE, data->cred);
gnutls_transport_set_push_function (data->sess, (gnutls_push_func) tls_push);
gnutls_transport_set_pull_function (data->sess, (gnutls_pull_func) tls_pull);
gnutls_transport_set_ptr (data->sess, data->prs);
ret = gnutls_handshake (data->sess);
if (ret != 0) {
gnutls_deinit (data->sess);
gnutls_certificate_free_credentials (data->cred);
return IKS_NET_TLSFAIL;
}
data->flags &= (~SF_TRY_SECURE);
data->flags |= SF_SECURE;
iks_send_header (data->prs, data->server);
return IKS_OK;
}
#endif
static void
insert_attribs (iks *x, char **atts)
{
if (atts) {
int i = 0;
while (atts[i]) {
iks_insert_attrib (x, atts[i], atts[i+1]);
i += 2;
}
}
}
#define CNONCE_LEN 4
static void
parse_digest (char *message, const char *key, char **value_ptr, char **value_end_ptr)
{
char *t;
*value_ptr = NULL;
*value_end_ptr = NULL;
t = strstr(message, key);
if (t) {
t += strlen(key);
*value_ptr = t;
while (t[0] != '\0') {
if (t[0] != '\\' && t[1] == '"') {
++t;
*value_end_ptr = t;
return;
}
++t;
}
}
}
static iks *
make_sasl_response (struct stream_data *data, char *message)
{
iks *x = NULL;
char *realm, *realm_end;
char *nonce, *nonce_end;
char cnonce[CNONCE_LEN*8 + 1];
iksmd5 *md5;
unsigned char a1_h[16], a1[33], a2[33], response_value[33];
char *response, *response_coded;
int i;
parse_digest(message, "realm=\"", &realm, &realm_end);
parse_digest(message, "nonce=\"", &nonce, &nonce_end);
/* nonce is necessary for auth */
if (!nonce || !nonce_end) return NULL;
*nonce_end = '\0';
/* if no realm is given use the server hostname */
if (realm) {
if (!realm_end) return NULL;
*realm_end = '\0';
} else {
realm = (char *) data->server;
}
/* generate random client challenge */
for (i = 0; i < CNONCE_LEN; ++i)
sprintf (cnonce + i*8, "%08x", rand());
md5 = iks_md5_new();
if (!md5) return NULL;
iks_md5_hash (md5, (const unsigned char*)data->auth_username, iks_strlen (data->auth_username), 0);
iks_md5_hash (md5, (const unsigned char*)":", 1, 0);
iks_md5_hash (md5, (const unsigned char*)realm, iks_strlen (realm), 0);
iks_md5_hash (md5, (const unsigned char*)":", 1, 0);
iks_md5_hash (md5, (const unsigned char*)data->auth_pass, iks_strlen (data->auth_pass), 1);
iks_md5_digest (md5, a1_h);
iks_md5_reset (md5);
iks_md5_hash (md5, (const unsigned char*)a1_h, 16, 0);
iks_md5_hash (md5, (const unsigned char*)":", 1, 0);
iks_md5_hash (md5, (const unsigned char*)nonce, iks_strlen (nonce), 0);
iks_md5_hash (md5, (const unsigned char*)":", 1, 0);
iks_md5_hash (md5, (const unsigned char*)cnonce, iks_strlen (cnonce), 1);
iks_md5_print (md5, (char*)a1);
iks_md5_reset (md5);
iks_md5_hash (md5, (const unsigned char*)"AUTHENTICATE:xmpp/", 18, 0);
iks_md5_hash (md5, (const unsigned char*)data->server, iks_strlen (data->server), 1);
iks_md5_print (md5, (char*)a2);
iks_md5_reset (md5);
iks_md5_hash (md5, (const unsigned char*)a1, 32, 0);
iks_md5_hash (md5, (const unsigned char*)":", 1, 0);
iks_md5_hash (md5, (const unsigned char*)nonce, iks_strlen (nonce), 0);
iks_md5_hash (md5, (const unsigned char*)":00000001:", 10, 0);
iks_md5_hash (md5, (const unsigned char*)cnonce, iks_strlen (cnonce), 0);
iks_md5_hash (md5, (const unsigned char*)":auth:", 6, 0);
iks_md5_hash (md5, (const unsigned char*)a2, 32, 1);
iks_md5_print (md5, (char*)response_value);
iks_md5_delete (md5);
i = iks_strlen (data->auth_username) + iks_strlen (realm) +
iks_strlen (nonce) + iks_strlen (data->server) +
CNONCE_LEN*8 + 136;
response = iks_malloc (i);
if (!response) return NULL;
sprintf (response, "username=\"%s\",realm=\"%s\",nonce=\"%s\""
",cnonce=\"%s\",nc=00000001,qop=auth,digest-uri=\""
"xmpp/%s\",response=%s,charset=utf-8",
data->auth_username, realm, nonce, cnonce,
data->server, response_value);
response_coded = iks_base64_encode (response, 0);
if (response_coded) {
x = iks_new ("response");
iks_insert_cdata (x, response_coded, 0);
iks_free (response_coded);
}
iks_free (response);
return x;
}
static void
iks_sasl_challenge (struct stream_data *data, iks *challenge)
{
char *message;
iks *x;
char *tmp;
tmp = iks_cdata (iks_child (challenge));
if (!tmp) return;
/* decode received blob */
message = iks_base64_decode (tmp);
if (!message) return;
/* reply the challenge */
if (strstr (message, "rspauth")) {
x = iks_new ("response");
} else {
x = make_sasl_response (data, message);
}
if (x) {
iks_insert_attrib (x, "xmlns", IKS_NS_XMPP_SASL);
iks_send (data->prs, x);
iks_delete (x);
}
iks_free (message);
}
static int
tagHook (struct stream_data *data, char *name, char **atts, int type)
{
iks *x;
int err;
switch (type) {
case IKS_OPEN:
case IKS_SINGLE:
#ifdef HAVE_GNUTLS
if (data->flags & SF_TRY_SECURE) {
if (strcmp (name, "proceed") == 0) {
err = handshake (data);
return err;
} else if (strcmp (name, "failure") == 0){
return IKS_NET_TLSFAIL;
}
}
#endif
if (data->current) {
x = iks_insert (data->current, name);
insert_attribs (x, atts);
} else {
x = iks_new (name);
insert_attribs (x, atts);
if (iks_strcmp (name, "stream:stream") == 0) {
err = data->streamHook (data->user_data, IKS_NODE_START, x);
if (err != IKS_OK) return err;
break;
}
}
data->current = x;
if (IKS_OPEN == type) break;
case IKS_CLOSE:
x = data->current;
if (NULL == x) {
err = data->streamHook (data->user_data, IKS_NODE_STOP, NULL);
if (err != IKS_OK) return err;
break;
}
if (NULL == iks_parent (x)) {
data->current = NULL;
if (iks_strcmp (name, "challenge") == 0) {
iks_sasl_challenge(data, x);
iks_delete (x);
} else if (iks_strcmp (name
没有合适的资源?快使用搜索试试~ 我知道了~
iksemel1.4
共111个文件
c:26个
po:14个
plo:12个
需积分: 10 18 下载量 107 浏览量
2016-07-26
11:49:24
上传
评论
收藏 709KB ZIP 举报
温馨提示
对iksemel中的jabber部分进行了封装。方便专注于业务,减少学习成本。
资源推荐
资源详情
资源评论
收起资源包目录
iksemel1.4 (111个子文件)
configure.ac 1KB
Makefile.am 923B
Makefile.am 484B
Makefile.am 443B
Makefile.am 424B
Makefile.am 217B
Makefile.am 130B
Makefile.am 94B
AUTHORS 320B
stream.c 15KB
sax.c 15KB
jxim.c 14KB
iks.c 14KB
tst-sax.c 10KB
iksroster.c 9KB
jabber.c 8KB
iksperf.c 6KB
tst-filter.c 6KB
ikslint.c 6KB
md5.c 5KB
ikstack.c 4KB
filter.c 4KB
dom.c 3KB
utility.c 3KB
io-posix.c 3KB
sha.c 3KB
tst-dom.c 3KB
hash.c 2KB
tst-iks.c 2KB
base64.c 2KB
tst-jid.c 2KB
tst-md5.c 2KB
perf.c 1KB
tst-ikstack.c 1KB
tst-sha.c 910B
ChangeLog 23KB
compile 32B
configure 418KB
COPYING 26KB
depcomp 17KB
config.guess 44KB
iksemel.h 12KB
config.h 3KB
jxim.h 2KB
finetune.h 898B
common.h 585B
perf.h 281B
HACKING 2KB
iksemel 57KB
Makefile.in 36KB
Makefile.in 33KB
Makefile.in 27KB
Makefile.in 23KB
Makefile.in 20KB
Makefile.in 18KB
Makefile.in 16KB
config.h.in 2KB
iksemel.pc.in 211B
INSTALL 8KB
install-sh 13KB
libtool 287KB
config.log 24KB
autoscan.log 3KB
aclocal.m4 344KB
Makefile 35KB
Makefile 30KB
Makefile 27KB
Makefile 23KB
Makefile 19KB
Makefile 18KB
Makefile 16KB
missing 11KB
NEWS 3KB
iksemel.pc 218B
libiksemel_la-io-posix.Plo 6KB
libiksemel_la-ikstack.Plo 5KB
libiksemel_la-utility.Plo 5KB
libiksemel_la-jabber.Plo 5KB
libiksemel_la-base64.Plo 5KB
libiksemel_la-stream.Plo 5KB
libiksemel_la-filter.Plo 5KB
libiksemel_la-sha.Plo 5KB
libiksemel_la-dom.Plo 5KB
libiksemel_la-sax.Plo 5KB
libiksemel_la-md5.Plo 5KB
libiksemel_la-iks.Plo 5KB
iksperf.Po 5KB
ikslint.Po 5KB
jxim.Po 5KB
iksroster.Po 5KB
hash.Po 5KB
tst-filter.Po 4KB
tst-jid.Po 4KB
tst-iks.Po 4KB
perf.Po 4KB
tst-ikstack.Po 4KB
tst-dom.Po 4KB
tst-sax.Po 4KB
tst-md5.Po 4KB
tst-sha.Po 4KB
共 111 条
- 1
- 2
资源评论
dn小小
- 粉丝: 17
- 资源: 11
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功