summary refs log tree commit diff stats
path: root/src/common/inbound.h
blob: e90ef8c3f6da2297fd3c91f78f6390199a806763 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/* HexChat
 * Copyright (C) 1998-2010 Peter Zelezny.
 * Copyright (C) 2009-2013 Berke Viktor.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#ifndef HEXCHAT_INBOUND_H
#define HEXCHAT_INBOUND_H

void inbound_next_nick (session *sess, char *nick);
void inbound_uback (server *serv);
void inbound_uaway (server *serv);
void inbound_account (server *serv, char *nick, char *account);
void inbound_part (server *serv, char *chan, char *user, char *ip, char *reason);
void inbound_upart (server *serv, char *chan, char *ip, char *reason);
void inbound_ukick (server *serv, char *chan, char *kicker, char *reason);
void inbound_kick (server *serv, char *chan, char *user, char *kicker, char *reason);
void inbound_notice (server *serv, char *to, char *nick, char *msg, char *ip, int id);
void inbound_quit (server *serv, char *nick, char *ip, char *reason);
void inbound_topicnew (server *serv, char *nick, char *chan, char *topic);
void inbound_join (server *serv, char *chan, char *user, char *ip, char *account, char *realname);
void inbound_ujoin (server *serv, char *chan, char *nick, char *ip);
void inbound_topictime (server *serv, char *chan, char *nick, time_t stamp);
void inbound_topic (server *serv, char *chan, char *topic_text);
void inbound_user_info_start (session *sess, char *nick);
void inbound_user_info (session *sess, char *chan, char *user, char *host, char *servname, char *nick, char *realname, char *account, unsigned int away);
void inbound_foundip (session *sess, char *ip);
int inbound_banlist (session *sess, time_t stamp, char *chan, char *mask, char *banner, int is_exemption);
void inbound_ping_reply (session *sess, char *timestring, char *from);
void inbound_nameslist (server *serv, char *chan, char *names);
int inbound_nameslist_end (server *serv, char *chan);
void inbound_away (server *serv, char *nick, char *msg);
void inbound_away_notify (server *serv, char *nick, char *reason);
void inbound_login_start (session *sess, char *nick, char *servname);
void inbound_login_end (session *sess, char *text);
void inbound_chanmsg (server *serv, session *sess, char *chan, char *from, char *text, char fromme, int id);
void clear_channel (session *sess);
void set_topic (session *sess, char *topic, char *stripped_topic);
void inbound_privmsg (server *serv, char *from, char *ip, char *text, int id);
void inbound_action (session *sess, char *chan, char *from, char *ip, char *text, int fromme, int id);
void inbound_newnick (server *serv, char *nick, char *newnick, int quiet);
void do_dns (session *sess, char *nick, char *host);
void inbound_identified (server *serv);
gboolean alert_match_word (char *word, char *masks);
gboolean alert_match_text (char *text, char *masks);

#endif
nse, sizeof (*response), 0)) < MSPROXY_MINLENGTH) { #ifdef DEBUG_MSPROXY printf ("recv_mspresponse(): expected to read atleast %d, read %d\n", MSPROXY_MINLENGTH, r); #endif return -1; } if (state->seq_recv == 0) break; /* not started incrementing yet. */ #ifdef DEBUG_MSPROXY if (response->sequence == state->seq_recv) printf ("seq_recv: %d, dup response, seqnumber: 0x%x\n", state->seq_recv, response->sequence); #endif } while (response->sequence == state->seq_recv); state->seq_recv = response->sequence; return r; } int traverse_msproxy (int sok, char *serverAddr, int port, struct msproxy_state_t *state, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound) { struct msproxy_request_t req; struct msproxy_response_t res; char *data, *p; char hostname[NT_MAXNAMELEN]; char ntdomain[NT_MAXNAMELEN]; char challenge[8]; netstore *ns_client; int clientport; guint32 destaddr; guint32 flags; if (!prefs.hex_net_proxy_auth || !prefs.hex_net_proxy_user[0] || !prefs.hex_net_proxy_pass[0] ) return 1; /* MS proxy protocol implementation currently doesn't support IPv6 */ destaddr = net_getsockaddr_v4 (ns_proxy); if (!destaddr) return 1; state->seq_recv = 0; state->seq_sent = 0; #ifdef DEBUG_MSPROXY printf ("Connecting to %s:%d via MS proxy\n", serverAddr, port); #endif gethostname (hostname, NT_MAXNAMELEN); p = strchr (hostname, '.'); if (p) *p = '\0'; bzero (&req, sizeof(req)); req.clientid = htonl(0x0a000000); /* Initial client ID is always 0x0a */ req.command = htons(MSPROXY_HELLO); /* HELLO command */ req.packet.hello.magic5 = htons(0x4b00); /* Fill in magic values */ req.packet.hello.magic10 = htons(0x1400); req.packet.hello.magic15 = htons(0x0400); req.packet.hello.magic20 = htons(0x5704); req.packet.hello.magic25 = htons(0x0004); req.packet.hello.magic30 = htons(0x0100); req.packet.hello.magic35 = htons(0x4a02); req.packet.hello.magic40 = htons(0x3000); req.packet.hello.magic45 = htons(0x4400); req.packet.hello.magic50 = htons(0x3900); data = req.packet.hello.data; strcpy (data, prefs.hex_net_proxy_user); /* Append a username */ data += strlen (prefs.hex_net_proxy_user)+2; /* +2 automatically creates second empty string */ strcpy (data, MSPROXY_EXECUTABLE); /* Append an application name */ data += strlen (MSPROXY_EXECUTABLE)+1; strcpy (data, hostname); /* Append a hostname */ data += strlen (hostname)+1; if (send_msprequest(sok, state, &req, data) == -1) return 1; if (recv_mspresponse(sok, state, &res) == -1) return 1; if (strcmp(res.RWSP, "RWSP") != 0) { #ifdef DEBUG_MSPROXY printf ("Received mailformed packet (no RWSP signature)\n"); #endif return 1; } if (ntohs(res.command) >> 8 != 0x10) { #ifdef DEBUG_MSPROXY printf ("expected res.command = 10??, is %x", ntohs(res.command)); #endif return 1; } state->clientid = htonl(rand()); state->serverid = res.serverid; #ifdef DEBUG_MSPROXY printf ("clientid: 0x%x, serverid: 0x%0x\n", state->clientid, state->serverid); printf ("packet #2\n"); #endif /* almost identical. */ req.clientid = state->clientid; req.serverid = state->serverid; if (send_msprequest(sok, state, &req, data) == -1) return 1; if (recv_mspresponse(sok, state, &res) == -1) return 1; if (res.serverid != state->serverid) { #ifdef DEBUG_MSPROXY printf ("expected serverid = 0x%x, is 0x%x\n",state->serverid, res.serverid); #endif return 1; } if (res.sequence != 0x01) { #ifdef DEBUG_MSPROXY printf ("expected res.sequence = 0x01, is 0x%x\n", res.sequence); #endif return 1; } if (ntohs(res.command) != MSPROXY_USERINFO_ACK) { #ifdef DEBUG_MSPROXY printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_USERINFO_ACK, ntohs(res.command)); #endif return 1; } #ifdef DEBUG_MSPROXY printf ("packet #3\n"); #endif bzero(&req, sizeof(req)); req.clientid = state->clientid; req.serverid = state->serverid; req.command = htons(MSPROXY_AUTHENTICATE); memcpy(req.packet.auth.NTLMSSP, "NTLMSSP", sizeof("NTLMSSP")); req.packet.auth.bindaddr = htonl(0x02000000); req.packet.auth.msgtype = htonl(0x01000000); /* NTLM flags: 0x80000000 Negotiate LAN Manager key 0x10000000 Negotiate sign 0x04000000 Request target 0x02000000 Negotiate OEM 0x00800000 Always sign 0x00020000 Negotiate NTLM */ req.packet.auth.flags = htonl(0x06020000); if (send_msprequest(sok, state, &req, &req.packet.auth.data) == -1) return 1; if (recv_mspresponse(sok, state, &res) == -1) return 1; if (res.serverid != state->serverid) { #ifdef DEBUG_MSPROXY printf ("expected serverid = 0x%x, is 0x%x\n", state->serverid, res.serverid); #endif return 1; } if (ntohs(res.command) != MSPROXY_AUTHENTICATE_ACK) { #ifdef DEBUG_MSPROXY printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_AUTHENTICATE_ACK, ntohs(res.command)); #endif return 1; } flags = res.packet.auth.flags & htonl(0x00020000); /* Remember if the server supports NTLM */ memcpy(challenge, &res.packet.auth.challenge, sizeof(challenge)); memcpy(ntdomain, &res.packet.auth.NTLMSSP[res.packet.auth.target.offset], res.packet.auth.target.len); ntdomain[res.packet.auth.target.len] = 0; #ifdef DEBUG_MSPROXY printf ("ntdomain: \"%s\"\n", ntdomain); printf ("packet #4\n"); #endif bzero(&req, sizeof(req)); req.clientid = state->clientid; req.serverid = state->serverid; req.command = htons(MSPROXY_AUTHENTICATE_2); /* Authentication response */ req.packet.auth2.magic3 = htons(0x0200); /* Something */ memcpy(req.packet.auth2.NTLMSSP, "NTLMSSP", sizeof("NTLMSSP")); /* Start of NTLM message */ req.packet.auth2.msgtype = htonl(0x03000000); /* Message type 2 */ req.packet.auth2.flags = flags | htonl(0x02000000); /* Choose authentication method */ data = req.packet.auth2.data; if (flags) { req.packet.auth2.lm_resp.len = 0; /* We are here if NTLM is supported, */ req.packet.auth2.lm_resp.alloc = 0; /* Do not fill in insecure LM response */ req.packet.auth2.lm_resp.offset = data - req.packet.auth2.NTLMSSP; req.packet.auth2.ntlm_resp.len = 24; /* Fill in NTLM response security buffer */ req.packet.auth2.ntlm_resp.alloc = 24; req.packet.auth2.ntlm_resp.offset = data - req.packet.auth2.NTLMSSP; ntlm_smb_nt_encrypt(prefs.hex_net_proxy_pass, challenge, data); /* Append an NTLM response */ data += 24; } else { req.packet.auth2.lm_resp.len = 24; /* Fill in LM response security buffer */ req.packet.auth2.lm_resp.alloc = 24; req.packet.auth2.lm_resp.offset = data - req.packet.auth2.NTLMSSP; ntlm_smb_encrypt(prefs.hex_net_proxy_pass, challenge, data); /* Append an LM response */ data += 24; req.packet.auth2.ntlm_resp.len = 0; /* NTLM response is empty */ req.packet.auth2.ntlm_resp.alloc = 0; req.packet.auth2.ntlm_resp.offset = data - req.packet.auth2.NTLMSSP; } req.packet.auth2.ntdomain_buf.len = strlen(ntdomain); /* Domain name */ req.packet.auth2.ntdomain_buf.alloc = req.packet.auth2.ntdomain_buf.len; req.packet.auth2.ntdomain_buf.offset = data - req.packet.auth2.NTLMSSP; strcpy(data, ntdomain); data += req.packet.auth2.ntdomain_buf.len; req.packet.auth2.username_buf.len = strlen(prefs.hex_net_proxy_user); /* Username */ req.packet.auth2.username_buf.alloc = req.packet.auth2.username_buf.len; req.packet.auth2.username_buf.offset = data - req.packet.auth2.NTLMSSP; strcpy(data, prefs.hex_net_proxy_user); data += req.packet.auth2.username_buf.len; req.packet.auth2.clienthost_buf.len = strlen(hostname); /* Hostname */ req.packet.auth2.clienthost_buf.alloc = req.packet.auth2.clienthost_buf.len; req.packet.auth2.clienthost_buf.offset = data - req.packet.auth2.NTLMSSP; strcpy(data, hostname); data += req.packet.auth2.clienthost_buf.len; req.packet.auth2.sessionkey_buf.len = 0; /* Session key (we don't use it) */ req.packet.auth2.sessionkey_buf.alloc = 0; req.packet.auth2.sessionkey_buf.offset = data - req.packet.auth2.NTLMSSP; if (send_msprequest(sok, state, &req, data) == -1) return 1; if (recv_mspresponse(sok, state, &res) == -1) return 1; if (res.serverid != state->serverid) { #ifdef DEBUG_MSPROXY printf ("expected res.serverid = 0x%x, is 0x%x\n", state->serverid, res.serverid); #endif return 1; } if (res.clientack != 0x01) { #ifdef DEBUG_MSPROXY printf ("expected res.clientack = 0x01, is 0x%x\n", res.clientack); #endif return 1; } if (ntohs(res.command) >> 8 != 0x47) { #ifdef DEBUG_MSPROXY printf ("expected res.command = 47??, is 0x%x\n", ntohs(res.command)); #endif return 1; } if (ntohs(res.command) == MSPROXY_AUTHENTICATE_2_NAK) { #ifdef DEBUG_MSPROXY printf ("Authentication failed\n"); #endif return -1; } #ifdef DEBUG_MSPROXY printf ("packet #5\n"); #endif bzero(&req, sizeof(req)); req.clientid = state->clientid; req.serverid = state->serverid; req.command = htons(MSPROXY_CONNECT); req.packet.connect.magic2 = htons(0x0200); req.packet.connect.magic6 = htons(0x0200); req.packet.connect.destport = htons(port); req.packet.connect.destaddr = destaddr; data = req.packet.connect.executable; strcpy(data, MSPROXY_EXECUTABLE); data += strlen(MSPROXY_EXECUTABLE) + 1; /* * need to tell server what port we will connect from, so we bind our sockets. */ ns_client = net_store_new (); if (!bound) { net_store_fill_any (ns_client); net_bind(ns_client, csok4, csok6); #ifdef DEBUG_MSPROXY perror ("bind() result"); #endif } clientport = net_getsockport(csok4, csok6); if (clientport == -1) { #ifdef DEBUG_MSPROXY printf ("Unable to obtain source port\n"); #endif return 1; } req.packet.connect.srcport = clientport; if (send_msprequest(sok, state, &req, data) == -1) return 1; if (recv_mspresponse(sok, state, &res) == -1) return 1; if (ntohs(res.command) != MSPROXY_CONNECT_ACK) { #ifdef DEBUG_MSPROXY printf ("expected res.command = 0x%x, is 0x%x\n",MSPROXY_CONNECT_ACK, ntohs(res.command)); #endif return 1; } net_store_fill_v4 (ns_client, res.packet.connect.clientaddr, res.packet.connect.clientport); #ifdef DEBUG_MSPROXY printf ("Connecting...\n"); #endif if (net_connect (ns_client, csok4, csok6, csok) != 0) { #ifdef DEBUG_MSPROXY printf ("Failed to connect to port %d\n", htons(res.packet.connect.clientport)); #endif net_store_destroy (ns_client); return 1; } net_store_destroy (ns_client); #ifdef DEBUG_MSPROXY printf ("packet #6\n"); #endif req.clientid = state->clientid; req.serverid = state->serverid; req.command = htons(MSPROXY_USERINFO_ACK); if (send_msprequest(sok, state, &req, req.packet.connack.data) == -1) return 1; return 0; } void msproxy_keepalive (void) { server *serv; GSList *list = serv_list; struct msproxy_request_t req; struct msproxy_response_t res; while (list) { serv = list->data; if (serv->connected && (serv->proxy_sok != -1)) { #ifdef DEBUG_MSPROXY printf ("sending MS proxy keepalive packet\n"); #endif bzero(&req, sizeof(req)); req.clientid = serv->msp_state.clientid; req.serverid = serv->msp_state.serverid; req.command = htons(MSPROXY_HELLO); if (send_msprequest(serv->proxy_sok, &serv->msp_state, &req, req.packet.hello.data) == -1) continue; recv_mspresponse(serv->proxy_sok, &serv->msp_state, &res); #ifdef DEBUG_MSPROXY if (ntohs(res.command) != MSPROXY_USERINFO_ACK) printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_USERINFO_ACK, ntohs(res.command)); #endif } list = list->next; } } #endif