Home | History | Annotate | Download | only in snoop
      1  0  stevel /*
      2  0  stevel  * CDDL HEADER START
      3  0  stevel  *
      4  0  stevel  * The contents of this file are subject to the terms of the
      5  0  stevel  * Common Development and Distribution License, Version 1.0 only
      6  0  stevel  * (the "License").  You may not use this file except in compliance
      7  0  stevel  * with the License.
      8  0  stevel  *
      9  0  stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  0  stevel  * or http://www.opensolaris.org/os/licensing.
     11  0  stevel  * See the License for the specific language governing permissions
     12  0  stevel  * and limitations under the License.
     13  0  stevel  *
     14  0  stevel  * When distributing Covered Code, include this CDDL HEADER in each
     15  0  stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  0  stevel  * If applicable, add the following below this CDDL HEADER, with the
     17  0  stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     18  0  stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  0  stevel  *
     20  0  stevel  * CDDL HEADER END
     21  0  stevel  */
     22  0  stevel /*
     23  0  stevel  * Copyright (c) 1998-1999,2001 by Sun Microsystems, Inc.
     24  0  stevel  * All rights reserved.
     25  0  stevel  */
     26  0  stevel 
     27  0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28  0  stevel 
     29  0  stevel #include <stdio.h>
     30  0  stevel #include <sys/socket.h>
     31  0  stevel #include <netinet/in.h>
     32  0  stevel #include <string.h>
     33  0  stevel #include "snoop.h"
     34  0  stevel 
     35  0  stevel static void put_method(char *cp, int method);
     36  0  stevel static void put_socks5_addr(char *cp, const unsigned char *buf, int fraglen);
     37  0  stevel static void put_socks4_res(char *cp, int code);
     38  0  stevel static void put_socks5_res(char *cp, int code);
     39  0  stevel 
     40  0  stevel int
     41  0  stevel interpret_socks_call(flags, line, fraglen)
     42  0  stevel 	int flags;
     43  0  stevel 	char *line;
     44  0  stevel 	int fraglen;
     45  0  stevel {
     46  0  stevel 	unsigned char	*buf = (unsigned char *)line;
     47  0  stevel 	char		*cp;
     48  0  stevel 	struct in_addr	ipaddr;
     49  0  stevel 	int		i, n;
     50  0  stevel 
     51  0  stevel 	if (flags & F_SUM) {
     52  0  stevel 	cp = get_sum_line();
     53  0  stevel 	if (fraglen >= 2) {
     54  0  stevel 		switch (buf[0]) {
     55  0  stevel 		case 4:		/* SOCKS4 */
     56  0  stevel 			n = buf[1];
     57  0  stevel 			switch (n) {
     58  0  stevel 			case 1:
     59  0  stevel 			case 2:
     60  0  stevel 				if (fraglen >= 8) {
     61  0  stevel 					(void) memcpy(&ipaddr, &buf[4],
     62  0  stevel 					    sizeof (ipaddr));
     63  0  stevel 					(void) sprintf(cp,
     64  0  stevel 					    "SOCKS4 %s %s:%u",
     65  0  stevel 					    addrtoname(AF_INET, &ipaddr),
     66  0  stevel 					    (n == 1)? "CONNECT": "BIND",
     67  0  stevel 					    (buf[2] << 8) | buf[3]);
     68  0  stevel 					cp += strlen(cp);
     69  0  stevel 					if (fraglen > 8) {
     70  0  stevel 						(void) sprintf(cp, " User=");
     71  0  stevel 						cp += strlen(cp);
     72  0  stevel 						for (i = 8;
     73  0  stevel 							i < 40 && i < fraglen;
     74  0  stevel 							++i) {
     75  0  stevel 							if (buf[i] == '\0')
     76  0  stevel 								break;
     77  0  stevel 							*cp++ = buf[i];
     78  0  stevel 						}
     79  0  stevel 						if (i == 40) {
     80  0  stevel 							*cp++ = '.';
     81  0  stevel 							*cp++ = '.';
     82  0  stevel 							*cp++ = '.';
     83  0  stevel 						}
     84  0  stevel 						*cp = '\0';
     85  0  stevel 					}
     86  0  stevel 				}
     87  0  stevel 				break;
     88  0  stevel 			default:
     89  0  stevel 				(void) sprintf(cp, "SOCKS4 OP=%u", n);
     90  0  stevel 			}
     91  0  stevel 			break;
     92  0  stevel 		case 5:		/* SOCKS5 */
     93  0  stevel 			n = buf[1];
     94  0  stevel 			if (2 + n == fraglen) {
     95  0  stevel 				(void) sprintf(cp,
     96  0  stevel 					"SOCKS5 CONTACT NMETHODS=%d:", n);
     97  0  stevel 				cp += strlen(cp);
     98  0  stevel 				for (i = 0; i < n && 2 + i < fraglen; ++i) {
     99  0  stevel 					put_method(cp, buf[2 + i]);
    100  0  stevel 					cp += strlen(cp);
    101  0  stevel 				}
    102  0  stevel 			} else if (fraglen >= 6 && buf[2] == 0) {
    103  0  stevel 				const char	*cmd;
    104  0  stevel 
    105  0  stevel 				if (n < 1 || n > 3) {
    106  0  stevel 					(void) sprintf(cp,
    107  0  stevel 						"SOCKS (send data): %s",
    108  0  stevel 						show_string(line, fraglen, 20));
    109  0  stevel 				} else {
    110  0  stevel 					switch (n) {
    111  0  stevel 					case 1:
    112  0  stevel 						cmd = "CONNECT";
    113  0  stevel 						break;
    114  0  stevel 					case 2:
    115  0  stevel 						cmd = "BIND";
    116  0  stevel 						break;
    117  0  stevel 					case 3:
    118  0  stevel 						cmd = "ASSOCIATE_UDP";
    119  0  stevel 						break;
    120  0  stevel 					}
    121  0  stevel 					(void) sprintf(cp, "SOCKS5 %s ", cmd);
    122  0  stevel 					cp += strlen(cp);
    123  0  stevel 					put_socks5_addr(cp, &buf[3],
    124  0  stevel 						fraglen - 3);
    125  0  stevel 				}
    126  0  stevel 			} else {
    127  0  stevel 				(void) sprintf(cp, "SOCKS (send data): %s",
    128  0  stevel 					show_string(line, fraglen, 20));
    129  0  stevel 			}
    130  0  stevel 			break;
    131  0  stevel 		default:
    132  0  stevel 			(void) sprintf(cp, "SOCKS (send data): %s",
    133  0  stevel 				show_string(line, fraglen, 20));
    134  0  stevel 		}
    135  0  stevel 	} else {
    136  0  stevel 		(void) sprintf(cp, "SOCKS (send data): %s",
    137  0  stevel 			show_string(line, fraglen, 20));
    138  0  stevel 	}
    139  0  stevel 
    140  0  stevel 	} /* if (flags & F_SUM) */
    141  0  stevel 
    142  0  stevel 	if (flags & F_DTAIL) {
    143  0  stevel 		show_header("SOCKS: ", "SOCKS Header", fraglen);
    144  0  stevel 		show_space();
    145  0  stevel 		cp = get_line(0, 0);
    146  0  stevel 		if (fraglen >= 2) {
    147  0  stevel 			switch (buf[0]) {
    148  0  stevel 			case 4:
    149  0  stevel 				(void) sprintf(cp, "Version = 4");
    150  0  stevel 				n = buf[1];
    151  0  stevel 				switch (n) {
    152  0  stevel 				case 1:
    153  0  stevel 				case 2:
    154  0  stevel 					(void) sprintf(get_line(0, 0),
    155  0  stevel 					    "Operation = %s",
    156  0  stevel 					    (n == 1)? "CONNECT": "BIND");
    157  0  stevel 					if (fraglen >= 8) {
    158  0  stevel 						(void) memcpy(&ipaddr, &buf[4],
    159  0  stevel 						    sizeof (ipaddr));
    160  0  stevel 						(void) sprintf(get_line(0, 0),
    161  0  stevel 						    "Destination = %s:%u",
    162  0  stevel 						    addrtoname(AF_INET,
    163  0  stevel 						    &ipaddr),
    164  0  stevel 						    (buf[2] << 8) | buf[3]);
    165  0  stevel 						if (fraglen > 8) {
    166  0  stevel 							cp = get_line(0, 0);
    167  0  stevel 							(void) sprintf(cp,
    168  0  stevel 							    "User = ");
    169  0  stevel 							cp += strlen(cp);
    170  0  stevel 							for (i = 8;
    171  0  stevel 								i < 40; ++i) {
    172  0  stevel 								if
    173  0  stevel 								(buf[i] == '\0')
    174  0  stevel 									break;
    175  0  stevel 								*cp++ = buf[i];
    176  0  stevel 							}
    177  0  stevel 							if (i == 40) {
    178  0  stevel 								*cp++ = '.';
    179  0  stevel 								*cp++ = '.';
    180  0  stevel 								*cp++ = '.';
    181  0  stevel 							}
    182  0  stevel 							*cp = '\0';
    183  0  stevel 						}
    184  0  stevel 					}
    185  0  stevel 					break;
    186  0  stevel 				default:
    187  0  stevel 					(void) sprintf(get_line(0, 0),
    188  0  stevel 					    "Operation = %u (unknown)", n);
    189  0  stevel 				}
    190  0  stevel 				break;
    191  0  stevel 			case 5:		/* SOCKS5 */
    192  0  stevel 				(void) sprintf(cp, "Version = 5");
    193  0  stevel 				n = buf[1];
    194  0  stevel 				if (2 + n == fraglen) {
    195  0  stevel 					(void) sprintf(get_line(0, 0),
    196  0  stevel 					    "Number of methods = %u", n);
    197  0  stevel 					for (i = 0;
    198  0  stevel 						i < n && 2 + i < fraglen; ++i) {
    199  0  stevel 						cp = get_line(0, 0);
    200  0  stevel 						(void) sprintf(cp,
    201  0  stevel 							"Method %3u =", i);
    202  0  stevel 						cp += strlen(cp);
    203  0  stevel 						put_method(cp, buf[2 + i]);
    204  0  stevel 					}
    205  0  stevel 				} else if (fraglen >= 6 && buf[2] == 0) {
    206  0  stevel 					const char	*cmd;
    207  0  stevel 					if (n < 1 || n > 3) {
    208  0  stevel 						(void) sprintf(cp,
    209  0  stevel 							"SOCKS (send data): %s",
    210  0  stevel 							show_string(line,
    211  0  stevel 							fraglen, 20));
    212  0  stevel 					} else {
    213  0  stevel 						switch (n) {
    214  0  stevel 						case 1:
    215  0  stevel 							cmd = "CONNECT";
    216  0  stevel 							break;
    217  0  stevel 						case 2:
    218  0  stevel 							cmd = "BIND";
    219  0  stevel 							break;
    220  0  stevel 						case 3:
    221  0  stevel 							cmd = "ASSOCIATE_UDP";
    222  0  stevel 							break;
    223  0  stevel 						}
    224  0  stevel 						(void) sprintf(get_line(0, 0),
    225  0  stevel 						    "Operation = %s ", cmd);
    226  0  stevel 						put_socks5_addr(get_line(0, 0),
    227  0  stevel 						    &buf[3], fraglen - 3);
    228  0  stevel 						break;
    229  0  stevel 					}
    230  0  stevel 				} else
    231  0  stevel 					(void) sprintf(cp,
    232  0  stevel 						" SOCKS (send data): %s",
    233  0  stevel 						show_string(line, fraglen,
    234  0  stevel 						20));
    235  0  stevel 				break;
    236  0  stevel 			default:
    237  0  stevel 				(void) sprintf(cp,
    238  0  stevel 					"SOCKS (send data): %s",
    239  0  stevel 					show_string(line, fraglen, 20));
    240  0  stevel 			}
    241  0  stevel 			show_space();
    242  0  stevel 		} else
    243  0  stevel 			(void) sprintf(cp,
    244  0  stevel 				"SOCKS (send data): %s",
    245  0  stevel 				show_string(line, fraglen, 20));
    246  0  stevel 	}
    247  0  stevel 
    248  0  stevel out:
    249  0  stevel 	return (fraglen);
    250  0  stevel }
    251  0  stevel 
    252  0  stevel int
    253  0  stevel interpret_socks_reply(flags, line, fraglen)
    254  0  stevel 	int flags;
    255  0  stevel 	char *line;
    256  0  stevel 	int fraglen;
    257  0  stevel {
    258  0  stevel 	unsigned char	*buf = (unsigned char *)line;
    259  0  stevel 	char		*cp;
    260  0  stevel 	struct in_addr	ipaddr;
    261  0  stevel 
    262  0  stevel 	if (flags & F_SUM) {
    263  0  stevel 		cp = get_sum_line();
    264  0  stevel 		if (fraglen >= 2) {
    265  0  stevel 			switch (buf[0]) {
    266  0  stevel 			case 0:
    267  0  stevel 				(void) sprintf(cp, "SOCKS4 ");
    268  0  stevel 				cp += strlen(cp);
    269  0  stevel 				if (fraglen >= 8) {
    270  0  stevel 					(void) memcpy(&ipaddr, &buf[4],
    271  0  stevel 					    sizeof (ipaddr));
    272  0  stevel 					(void) sprintf(cp, "%s:%u ",
    273  0  stevel 					    addrtoname(AF_INET, &ipaddr),
    274  0  stevel 					    (buf[2] << 8) | buf[3]);
    275  0  stevel 					cp += strlen(cp);
    276  0  stevel 				}
    277  0  stevel 				/* reply version, no SOCKS version in v4 */
    278  0  stevel 				put_socks4_res(cp, buf[1]);
    279  0  stevel 				break;
    280  0  stevel 			case 5:
    281  0  stevel 				(void) sprintf(cp, "SOCKS5 method accepted:");
    282  0  stevel 				cp += strlen(cp);
    283  0  stevel 				put_method(cp, buf[1]);
    284  0  stevel 				break;
    285  0  stevel 			default:
    286  0  stevel 				(void) sprintf(cp, "SOCKS (recv data)");
    287  0  stevel 			}
    288  0  stevel 		} else
    289  0  stevel 			(void) sprintf(cp, "SOCKS (recv data)");
    290  0  stevel 	}
    291  0  stevel 
    292  0  stevel 	if (flags & F_DTAIL) {
    293  0  stevel 		show_header("SOCKS: ", "SOCKS Header", fraglen);
    294  0  stevel 		show_space();
    295  0  stevel 		cp = get_line(0, 0);
    296  0  stevel 		if (fraglen >= 2) {
    297  0  stevel 			switch (buf[0]) {
    298  0  stevel 			case 0:
    299  0  stevel 				/* reply version, no SOCKS version in v4 */
    300  0  stevel 				(void) sprintf(cp,
    301  0  stevel 				    "Reply version = 0 (SOCKS version 4)");
    302  0  stevel 				if (fraglen >= 8) {
    303  0  stevel 					(void) memcpy(&ipaddr, &buf[4],
    304  0  stevel 					    sizeof (ipaddr));
    305  0  stevel 					(void) sprintf(get_line(0, 0),
    306  0  stevel 					    "Destination %s:%u ",
    307  0  stevel 					    addrtoname(AF_INET, &ipaddr),
    308  0  stevel 					    (buf[2] << 8) | buf[3]);
    309  0  stevel 				}
    310  0  stevel 				cp = get_line(0, 0);
    311  0  stevel 				(void) sprintf(cp, "Result code = %u ", buf[1]);
    312  0  stevel 				cp += strlen(cp);
    313  0  stevel 				put_socks4_res(cp, buf[1]);
    314  0  stevel 				break;
    315  0  stevel 			case 5:
    316  0  stevel 				(void) sprintf(cp, "Reply version = 5");
    317  0  stevel 				if (fraglen == 2) {
    318  0  stevel 					cp = get_line(0, 0);
    319  0  stevel 					(void) sprintf(cp, "Method accepted =");
    320  0  stevel 					cp += strlen(cp);
    321  0  stevel 					put_method(cp, buf[1]);
    322  0  stevel 				} else if (fraglen >= 6 && buf[2] == 0x00) {
    323  0  stevel 					cp = get_line(0, 0);
    324  0  stevel 					(void) sprintf(cp, "Status = ");
    325  0  stevel 					cp += strlen(cp);
    326  0  stevel 					put_socks5_res(cp, buf[1]);
    327  0  stevel 					put_socks5_addr(get_line(0, 0),
    328  0  stevel 					    &buf[3], fraglen - 3);
    329  0  stevel 				}
    330  0  stevel 				break;
    331  0  stevel 			default:
    332  0  stevel 				(void) sprintf(cp, "(recv data)");
    333  0  stevel 			}
    334  0  stevel 		} else
    335  0  stevel 			(void) sprintf(cp, "(recv data)");
    336  0  stevel 		show_space();
    337  0  stevel 	}
    338  0  stevel 
    339  0  stevel out:
    340  0  stevel 	return (fraglen);
    341  0  stevel }
    342  0  stevel 
    343  0  stevel static void
    344  0  stevel put_method(char *cp, int method)
    345  0  stevel {
    346  0  stevel 	switch (method) {
    347  0  stevel 	case 0:
    348  0  stevel 		(void) sprintf(cp, " NOAUTH");
    349  0  stevel 		break;
    350  0  stevel 	case 1:
    351  0  stevel 		(void) sprintf(cp, " GSSAPI");
    352  0  stevel 		break;
    353  0  stevel 	case 2:
    354  0  stevel 		(void) sprintf(cp, " USERNAME/PASSWD");
    355  0  stevel 		break;
    356  0  stevel 	case 255:
    357  0  stevel 		(void) sprintf(cp, " NONE");
    358  0  stevel 		break;
    359  0  stevel 	default:
    360  0  stevel 		(void) sprintf(cp, " 0x%02x (unknown)", method);
    361  0  stevel 	}
    362  0  stevel }
    363  0  stevel 
    364  0  stevel static void
    365  0  stevel put_socks5_addr(char *cp, const unsigned char *buf, int fraglen)
    366  0  stevel {
    367  0  stevel 	struct in_addr	ipaddr;
    368  0  stevel 	int		i;
    369  0  stevel 
    370  0  stevel 	switch (buf[0]) {
    371  0  stevel 	case 1:
    372  0  stevel 		/* IPv4 */
    373  0  stevel 		(void) sprintf(cp, "Address = ");
    374  0  stevel 		cp += strlen(cp);
    375  0  stevel 		if (1 + 4 + 2 <= fraglen) {
    376  0  stevel 			(void) memcpy(&ipaddr, &buf[1], sizeof (ipaddr));
    377  0  stevel 			(void) sprintf(cp, "%s:%u",
    378  0  stevel 			    addrtoname(AF_INET, &ipaddr),
    379  0  stevel 			    (buf[5] << 8) | buf[5 + 1]);
    380  0  stevel 		} else
    381  0  stevel 			(void) strcat(cp, "(IPv4)");
    382  0  stevel 		break;
    383  0  stevel 	case 3:
    384  0  stevel 		/* domain name */
    385  0  stevel 		(void) sprintf(cp, "Domain name = ");
    386  0  stevel 		cp += strlen(cp);
    387  0  stevel 		for (i = 0; i <= buf[1] && 1 + i < fraglen; ++i)
    388  0  stevel 			*cp++ = buf[1 + i];
    389  0  stevel 		if (1 + i + 2 <= fraglen)
    390  0  stevel 			(void) sprintf(cp, ":%u",
    391  0  stevel 			    (buf[1 + i] << 8) | buf[1 + i + 1]);
    392  0  stevel 		else
    393  0  stevel 			*cp = '\0';
    394  0  stevel 		break;
    395  0  stevel 	case 4:
    396  0  stevel 		/* IPv6 */
    397  0  stevel 		(void) sprintf(cp, "Address = ");
    398  0  stevel 		if (1 + 16 <= fraglen) {
    399  0  stevel 			for (i = 0; i < 16; ++i) {
    400  0  stevel 				if (i > 0)
    401  0  stevel 					*cp++ = '.';
    402  0  stevel 				(void) sprintf(cp, "%u", buf[1 + i]);
    403  0  stevel 				cp += strlen(cp);
    404  0  stevel 			}
    405  0  stevel 			if (1 + 16 + 2 <= fraglen) {
    406  0  stevel 				(void) sprintf(cp, ":%u",
    407  0  stevel 				    (buf[1 + 16] << 8) | buf[1 + 16 + 1]);
    408  0  stevel 			}
    409  0  stevel 		} else
    410  0  stevel 			(void) strcat(cp, "(IPv6)");
    411  0  stevel 		break;
    412  0  stevel 	default:
    413  0  stevel 		(void) sprintf(cp, "Address type = 0x%02x (unknown)", buf[0]);
    414  0  stevel 	}
    415  0  stevel }
    416  0  stevel 
    417  0  stevel static void
    418  0  stevel put_socks4_res(char *cp, int code)
    419  0  stevel {
    420  0  stevel 	switch (code) {
    421  0  stevel 	case 90:
    422  0  stevel 		(void) sprintf(cp, "request granted");
    423  0  stevel 		break;
    424  0  stevel 	case 91:
    425  0  stevel 		(void) sprintf(cp, "request rejected or failed");
    426  0  stevel 		break;
    427  0  stevel 	case 92:
    428  0  stevel 		(void) sprintf(cp, "socksd can't connect to client's identd");
    429  0  stevel 		break;
    430  0  stevel 	case 93:
    431  0  stevel 		(void) sprintf(cp, "identity mismatch");
    432  0  stevel 		break;
    433  0  stevel 	default:
    434  0  stevel 		(void) sprintf(cp, "0x%02x (unknown)", code);
    435  0  stevel 	}
    436  0  stevel }
    437  0  stevel 
    438  0  stevel static void
    439  0  stevel put_socks5_res(char *cp, int code)
    440  0  stevel {
    441  0  stevel 	switch (code) {
    442  0  stevel 	case 0:
    443  0  stevel 		(void) strcpy(cp, "succeeded");
    444  0  stevel 		break;
    445  0  stevel 	case 1:
    446  0  stevel 		(void) strcpy(cp, "general SOCKS server failure");
    447  0  stevel 		break;
    448  0  stevel 	case 2:
    449  0  stevel 		(void) strcpy(cp, "connection not allowed by ruleset");
    450  0  stevel 		break;
    451  0  stevel 	case 3:
    452  0  stevel 		(void) strcpy(cp, "network unreachable");
    453  0  stevel 		break;
    454  0  stevel 	case 4:
    455  0  stevel 		(void) strcpy(cp, "host unreachable");
    456  0  stevel 		break;
    457  0  stevel 	case 5:
    458  0  stevel 		(void) strcpy(cp, "connection refused");
    459  0  stevel 		break;
    460  0  stevel 	case 6:
    461  0  stevel 		(void) strcpy(cp, "TTL expired");
    462  0  stevel 		break;
    463  0  stevel 	case 7:
    464  0  stevel 		(void) strcpy(cp, "command not supported");
    465  0  stevel 		break;
    466  0  stevel 	case 8:
    467  0  stevel 		(void) strcpy(cp, "address type not supported");
    468  0  stevel 		break;
    469  0  stevel 	default:
    470  0  stevel 		(void) sprintf(cp, "code 0x%02x", code);
    471  0  stevel 	}
    472  0  stevel }
    473