Mercurial > pidgin
comparison src/proxy.c @ 12391:804e335b7b62
[gaim-migrate @ 14698]
This is NTLM authentication for HTTP proxies, contributed by Thomas
Butter with testing and bugfixing by Praveen Karadakal.
committer: Tailor Script <tailor@pidgin.im>
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Thu, 08 Dec 2005 03:28:42 +0000 |
parents | 9ed903d0c619 |
children | a88ca6da0b38 |
comparison
equal
deleted
inserted
replaced
12390:dca3779701a7 | 12391:804e335b7b62 |
---|---|
31 | 31 |
32 #include "internal.h" | 32 #include "internal.h" |
33 #include "cipher.h" | 33 #include "cipher.h" |
34 #include "debug.h" | 34 #include "debug.h" |
35 #include "notify.h" | 35 #include "notify.h" |
36 #include "ntlm.h" | |
36 #include "prefs.h" | 37 #include "prefs.h" |
37 #include "proxy.h" | 38 #include "proxy.h" |
38 #include "util.h" | 39 #include "util.h" |
39 | 40 |
40 static GaimProxyInfo *global_proxy_info = NULL; | 41 static GaimProxyInfo *global_proxy_info = NULL; |
1049 static void | 1050 static void |
1050 http_canread(gpointer data, gint source, GaimInputCondition cond) | 1051 http_canread(gpointer data, gint source, GaimInputCondition cond) |
1051 { | 1052 { |
1052 int nlc = 0; | 1053 int nlc = 0; |
1053 int pos = 0; | 1054 int pos = 0; |
1054 int minor, major, status, error=0; | 1055 int minor, major, status = 0, error=0; |
1055 struct PHB *phb = data; | 1056 struct PHB *phb = data; |
1056 char inputline[8192], *p; | 1057 char inputline[8192], *p; |
1057 | 1058 |
1058 gaim_input_remove(phb->inpa); | |
1059 | 1059 |
1060 while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) { | 1060 while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) { |
1061 if (inputline[pos - 1] == '\n') | 1061 if (inputline[pos - 1] == '\n') |
1062 nlc++; | 1062 nlc++; |
1063 else if (inputline[pos - 1] != '\r') | 1063 else if (inputline[pos - 1] != '\r') |
1080 error = (*p!=' '); | 1080 error = (*p!=' '); |
1081 } | 1081 } |
1082 } | 1082 } |
1083 } | 1083 } |
1084 | 1084 |
1085 /* Read the contents */ | |
1086 p = g_strrstr(inputline, "Content-Length: "); | |
1087 if(p>0) { | |
1088 gchar *tmp; | |
1089 int len = 0; | |
1090 char tmpc; | |
1091 p += strlen("Content-Length: "); | |
1092 tmp = strchr(p, '\r'); | |
1093 *tmp = 0; | |
1094 len = atoi(p); | |
1095 *tmp = '\r'; | |
1096 while(len--) read(source, &tmpc, 1); | |
1097 } | |
1085 if(error) { | 1098 if(error) { |
1086 gaim_debug_error("proxy", | 1099 gaim_debug_error("proxy", |
1087 "Unable to parse proxy's response: %s\n", inputline); | 1100 "Unable to parse proxy's response: %s\n", inputline); |
1088 close(source); | 1101 close(source); |
1089 source=-1; | 1102 source=-1; |
1090 } | 1103 } |
1091 else if(status!=200) { | 1104 else if(status!=200) { |
1092 gaim_debug_error("proxy", | 1105 gaim_debug_error("proxy", |
1093 "Proxy server replied with:\n%s\n", p); | 1106 "Proxy server replied with:\n%s\n", inputline); |
1094 close(source); | |
1095 source = -1; | |
1096 | 1107 |
1097 /* XXX: why in the hell are we calling gaim_connection_error() here? */ | 1108 /* XXX: why in the hell are we calling gaim_connection_error() here? */ |
1109 if ( status == 407 /* Proxy Auth */ ) { | |
1110 gchar *ntlm; | |
1111 if( (ntlm = g_strrstr(inputline, "Proxy-Authenticate: NTLM "))) { /* Check for Type-2 */ | |
1112 gchar *nonce = ntlm; | |
1113 gchar *domain = (gchar*)gaim_proxy_info_get_username(phb->gpi); | |
1114 gchar *username; | |
1115 gchar *request; | |
1116 gchar *response; | |
1117 if(!(username = strchr(domain, '\\'))) { | |
1118 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); | |
1119 close(source); | |
1120 source = -1; | |
1121 gaim_connection_error(phb->account->gc, msg); | |
1122 g_free(msg); | |
1123 gaim_input_remove(phb->inpa); | |
1124 return; | |
1125 } | |
1126 *username = 0; | |
1127 username ++; | |
1128 ntlm += strlen("Proxy-Authenticate: NTLM "); | |
1129 while(*nonce != '\r' && *nonce != '\0') nonce ++; | |
1130 *nonce = 0; | |
1131 nonce = gaim_ntlm_parse_type2(ntlm); | |
1132 response = gaim_ntlm_gen_type3(username, (gchar*)gaim_proxy_info_get_password(phb->gpi), (gchar*)gaim_proxy_info_get_host(phb->gpi), domain, nonce); | |
1133 username--; | |
1134 *username = '\\'; | |
1135 request = g_strdup_printf("CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\nProxy-Authorization: NTLM %s\r\nProxy-Connection: Keep-Alive\r\n\r\n", | |
1136 phb->host, phb->port, phb->host, phb->port, | |
1137 response); | |
1138 write(source, request, strlen(request)); | |
1139 g_free(request); | |
1140 g_free(response); | |
1141 return; | |
1142 } else if((ntlm = g_strrstr(inputline, "Proxy-Authenticate: NTLM"))) { /* Empty message */ | |
1143 gchar request[2048]; | |
1144 gchar *domain = (gchar*)gaim_proxy_info_get_username(phb->gpi); | |
1145 gchar *username; | |
1146 int request_len; | |
1147 if(!(username = strchr(domain, '\\'))) { | |
1148 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); | |
1149 close(source); | |
1150 source = -1; | |
1151 gaim_connection_error(phb->account->gc, msg); | |
1152 g_free(msg); | |
1153 gaim_input_remove(phb->inpa); | |
1154 return; | |
1155 } | |
1156 *username = 0; | |
1157 | |
1158 request_len = g_snprintf(request, sizeof(request), | |
1159 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", | |
1160 phb->host, phb->port, phb->host, phb->port); | |
1161 | |
1162 g_return_if_fail(request_len < sizeof(request)); | |
1163 request_len += g_snprintf(request + request_len, | |
1164 sizeof(request) - request_len, | |
1165 "Proxy-Authorization: NTLM %s\r\nProxy-Connection: Keep-Alive\r\n\r\n", gaim_ntlm_gen_type1((gchar*)gaim_proxy_info_get_host(phb->gpi),domain)); | |
1166 *username = '\\'; | |
1167 write(source, request, request_len); | |
1168 return; | |
1169 } else { | |
1170 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); | |
1171 close(source); | |
1172 source = -1; | |
1173 gaim_connection_error(phb->account->gc, msg); | |
1174 g_free(msg); | |
1175 } | |
1176 } | |
1098 if ( status == 403 /* Forbidden */ ) { | 1177 if ( status == 403 /* Forbidden */ ) { |
1099 gchar *msg = g_strdup_printf(_("Access denied: proxy server forbids port %d tunnelling."), phb->port); | 1178 gchar *msg = g_strdup_printf(_("Access denied: proxy server forbids port %d tunnelling."), phb->port); |
1100 gaim_connection_error(phb->account->gc, msg); | 1179 gaim_connection_error(phb->account->gc, msg); |
1101 g_free(msg); | 1180 g_free(msg); |
1102 } else { | 1181 } else { |
1103 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); | 1182 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); |
1104 gaim_connection_error(phb->account->gc, msg); | 1183 gaim_connection_error(phb->account->gc, msg); |
1105 g_free(msg); | 1184 g_free(msg); |
1106 } | 1185 } |
1107 | |
1108 } else { | 1186 } else { |
1109 http_complete(phb, source); | 1187 http_complete(phb, source); |
1110 } | 1188 } |
1111 | 1189 |
1190 gaim_input_remove(phb->inpa); | |
1112 return; | 1191 return; |
1113 } | 1192 } |
1114 | 1193 |
1115 static void | 1194 static void |
1116 http_canwrite(gpointer data, gint source, GaimInputCondition cond) | 1195 http_canwrite(gpointer data, gint source, GaimInputCondition cond) |
1147 gaim_proxy_info_get_password(phb->gpi) ? | 1226 gaim_proxy_info_get_password(phb->gpi) ? |
1148 gaim_proxy_info_get_password(phb->gpi) : ""); | 1227 gaim_proxy_info_get_password(phb->gpi) : ""); |
1149 t2 = gaim_base64_encode((const guchar *)t1, strlen(t1)); | 1228 t2 = gaim_base64_encode((const guchar *)t1, strlen(t1)); |
1150 g_free(t1); | 1229 g_free(t1); |
1151 g_return_if_fail(request_len < sizeof(request)); | 1230 g_return_if_fail(request_len < sizeof(request)); |
1231 | |
1152 request_len += g_snprintf(request + request_len, | 1232 request_len += g_snprintf(request + request_len, |
1153 sizeof(request) - request_len, | 1233 sizeof(request) - request_len, |
1154 "Proxy-Authorization: Basic %s\r\n", t2); | 1234 "Proxy-Authorization: NTLM %s\r\nProxy-Authorization: Basic %s\r\nProxy-Connection: Keep-Alive\r\n", gaim_ntlm_gen_type1((gchar*)gaim_proxy_info_get_host(phb->gpi),""), t2); |
1155 g_free(t2); | 1235 g_free(t2); |
1156 } | 1236 } |
1157 | 1237 |
1158 g_return_if_fail(request_len < sizeof(request)); | 1238 g_return_if_fail(request_len < sizeof(request)); |
1159 strcpy(request + request_len, "\r\n"); | 1239 strcpy(request + request_len, "\r\n"); |