#include #ifndef lint #if 0 static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93"; #else __IDSTRING(yyrcsid, "$NetBSD: skeleton.c,v 1.14 1997/10/20 03:41:16 lukem Exp $"); #endif #endif #include #define YYBYACC 1 #define YYMAJOR 1 #define YYMINOR 9 #define YYLEX yylex() #define YYEMPTY -1 #define yyclearin (yychar=(YYEMPTY)) #define yyerrok (yyerrflag=0) #define YYRECOVERING (yyerrflag!=0) #define YYPREFIX "yy" #line 42 "ftpcmd.y" #ifndef lint #if 0 static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94"; #endif #endif /* not lint */ #if 0 #include __FBSDID("$FreeBSD: src/libexec/ftpd/ftpcmd.y,v 1.64 2004/11/18 13:46:29 yar Exp $"); #endif #include #include #include #include #include #include #include #ifdef LINUX /* Linux port */ #include "bsdglob.h" #else /* BSD source */ #include #endif /* BSD source */ #include #ifdef USE_MD5 #ifdef USE_SSL #include "md5hl.h" #else /* !USE_SSL */ #include #endif /* USE_SSL */ #endif /* USE_MD5 */ #include #include #include #include #include #include #include #include #include #include #include "extern.h" #include "pathnames.h" #ifdef LINUX /* Linux port */ #include #endif /* Linux port */ #include #include "ssl_port_ftpd.h" #ifdef USE_SSL #include "sslapp.h" extern void do_ssl_start(); #endif /* USE_SSL */ extern union sockunion data_dest, his_addr; extern int hostinfo; extern int logged_in; extern struct passwd *pw; extern int guest; extern char *homedir; extern int ftpdparanoid; extern int logging; extern int type; extern int form; extern int ftpdebug; extern int timeout; extern int maxtimeout; extern int pdata; extern char *hostname; extern char proctitle[]; extern int usedefault; extern char tmpline[]; extern int readonly; extern int noepsv; extern int noretr; extern int noguestretr; extern char *typenames[]; /* defined in included from ftpd.c */ off_t restart_point; static int cmd_type; static int cmd_form; static int cmd_bytesz; static int state; char cbuf[512]; char *fromname = NULL; extern int epsvall; #line 141 "ftpcmd.y" typedef union { struct { off_t o; int i; } u; char *s; } YYSTYPE; #line 126 "ftpcmd.c" #define A 257 #define B 258 #define C 259 #define E 260 #define F 261 #define I 262 #define L 263 #define N 264 #define P 265 #define R 266 #define S 267 #define T 268 #define ALL 269 #define SP 270 #define CRLF 271 #define COMMA 272 #define USER 273 #define PASS 274 #define ACCT 275 #define REIN 276 #define QUIT 277 #define PORT 278 #define PASV 279 #define TYPE 280 #define STRU 281 #define MODE 282 #define RETR 283 #define STOR 284 #define APPE 285 #define MLFL 286 #define MAIL 287 #define MSND 288 #define MSOM 289 #define MSAM 290 #define MRSQ 291 #define MRCP 292 #define ALLO 293 #define REST 294 #define RNFR 295 #define RNTO 296 #define ABOR 297 #define DELE 298 #define CWD 299 #define LIST 300 #define NLST 301 #define SITE 302 #define STAT 303 #define HELP 304 #define NOOP 305 #define MKD 306 #define RMD 307 #define PWD 308 #define CDUP 309 #define STOU 310 #define SMNT 311 #define SYST 312 #define SIZE 313 #define MDTM 314 #define LPRT 315 #define LPSV 316 #define EPRT 317 #define EPSV 318 #define UMASK 319 #define IDLE 320 #define CHMOD 321 #define MDFIVE 322 #define FEAT 323 #define OPTS 324 #define AUTH 325 #define PROT 326 #define PBSZ 327 #define LEXERR 328 #define NOTIMPL 329 #define SYNTERR 330 #define STRING 331 #define NUMBER 332 #define YYERRCODE 256 short yylhs[] = { -1, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 13, 12, 12, 16, 17, 3, 15, 20, 21, 21, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 7, 7, 7, 11, 10, 2, 1, 5, 4, 14, }; short yylen[] = { 2, 0, 2, 2, 4, 4, 5, 4, 4, 2, 5, 5, 5, 3, 3, 5, 5, 3, 5, 5, 5, 5, 9, 5, 5, 5, 3, 5, 3, 5, 5, 3, 5, 5, 3, 3, 5, 2, 4, 2, 5, 5, 3, 3, 4, 6, 7, 5, 7, 9, 5, 7, 5, 3, 5, 5, 2, 4, 2, 1, 3, 1, 3, 1, 5, 5, 1, 0, 1, 1, 1, 1, 1, 11, 41, 17, 1, 1, 1, 1, 3, 1, 3, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, }; short yydefred[] = { 1, 0, 63, 0, 0, 0, 96, 96, 96, 96, 96, 96, 98, 98, 96, 96, 98, 98, 96, 98, 96, 96, 96, 0, 96, 0, 0, 98, 98, 96, 96, 98, 96, 96, 96, 96, 96, 97, 97, 0, 0, 0, 99, 0, 59, 61, 2, 3, 0, 0, 9, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 66, 0, 68, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 35, 0, 28, 0, 26, 0, 96, 98, 96, 60, 62, 0, 0, 31, 0, 0, 0, 42, 43, 0, 53, 0, 0, 0, 14, 0, 0, 17, 0, 69, 0, 0, 72, 0, 7, 8, 0, 0, 0, 0, 83, 0, 0, 87, 89, 88, 0, 91, 92, 90, 0, 94, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 4, 70, 0, 5, 0, 10, 0, 0, 0, 71, 86, 18, 19, 20, 23, 24, 25, 0, 21, 65, 64, 33, 32, 36, 29, 27, 0, 0, 47, 0, 0, 0, 50, 30, 40, 41, 52, 54, 55, 0, 11, 12, 16, 15, 6, 0, 78, 76, 77, 80, 82, 85, 0, 45, 95, 0, 0, 0, 0, 0, 0, 0, 48, 0, 46, 51, 0, 0, 0, 0, 0, 0, 22, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, }; short yydgoto[] = { 1, 52, 248, 203, 58, 84, 156, 160, 152, 242, 162, 163, 94, 92, 89, 143, 140, 195, 46, 47, 147, 188, }; short yysindex[] = { 0, -121, 0, -257, -220, -268, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -255, 0, -208, -254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -229, -251, -226, 0, -222, 0, 0, 0, 0, -309, -278, 0, 0, -214, -207, -204, -195, -190, -184, -177, -165, -164, -163, -162, -161, -182, -160, -199, -197, -186, -252, -180, -239, 0, 0, -159, -158, -157, -156, -154, -153, -151, -150, -149, -148, -146, -175, 0, -218, -206, -144, -215, 0, -143, 0, -142, -202, 0, -181, -178, -249, -200, -200, -200, -198, -196, -200, -200, 0, -200, -200, 0, -200, 0, -200, 0, -173, 0, 0, 0, 0, 0, -188, -200, 0, -138, -200, -200, 0, 0, -200, 0, -200, -200, -194, 0, -192, -267, 0, -134, 0, -131, -189, 0, -127, 0, 0, -126, -124, -125, -122, 0, -264, -120, 0, 0, 0, -117, 0, 0, 0, -106, 0, 0, -105, -104, -103, -171, -102, -100, -81, -73, -72, -71, -70, -119, 0, -169, -63, -60, -167, -58, 0, -57, -56, -55, -54, -53, -123, -52, -51, -50, -49, 0, 0, 0, -48, 0, -108, 0, -248, -248, -107, 0, 0, 0, 0, 0, 0, 0, 0, -116, 0, 0, 0, 0, 0, 0, 0, 0, -45, -98, 0, -98, -200, -97, 0, 0, 0, 0, 0, 0, 0, -96, 0, 0, 0, 0, 0, -61, 0, 0, 0, 0, 0, 0, -43, 0, 0, -42, -40, -39, -38, -44, -95, -94, 0, -200, 0, 0, -93, -41, -31, -30, -29, -90, 0, 0, -88, -27, -26, -85, -84, -23, -22, -80, -79, 0, -21, -78, -17, -76, -15, -74, -13, -69, -12, -68, -11, -67, -10, -66, -5, -64, -3, -62, -1, -59, 2, -47, 3, -46, 4, -37, 5, -36, 6, -35, 0, }; short yyrindex[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; short yygindex[] = { 0, 25, 59, 83, 10, 132, 0, 0, 0, 88, -99, -101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; #define YYTABLESIZE 297 short yytable[] = { 164, 165, 190, 51, 168, 169, 201, 170, 171, 157, 158, 239, 172, 48, 173, 69, 240, 73, 159, 87, 241, 180, 91, 59, 182, 183, 62, 63, 184, 65, 185, 186, 53, 54, 55, 56, 57, 74, 75, 60, 61, 78, 86, 64, 88, 66, 67, 68, 90, 70, 49, 50, 115, 93, 76, 77, 95, 79, 80, 81, 82, 83, 71, 72, 96, 191, 97, 116, 202, 117, 118, 109, 110, 111, 112, 98, 148, 119, 120, 149, 99, 150, 151, 153, 113, 114, 100, 154, 155, 107, 122, 123, 124, 101, 121, 136, 137, 174, 175, 210, 211, 220, 221, 224, 225, 102, 103, 104, 105, 106, 108, 125, 126, 138, 127, 128, 129, 142, 130, 131, 132, 133, 250, 134, 135, 139, 141, 177, 144, 145, 146, 161, 179, 181, 166, 2, 167, 192, 187, 189, 193, 176, 194, 178, 196, 199, 197, 198, 200, 232, 245, 204, 3, 4, 205, 262, 5, 6, 7, 8, 9, 10, 11, 12, 13, 206, 207, 208, 209, 212, 85, 213, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 214, 32, 33, 34, 35, 36, 37, 38, 215, 216, 217, 218, 39, 40, 41, 42, 43, 222, 44, 45, 223, 253, 219, 226, 227, 228, 229, 230, 231, 233, 234, 235, 236, 237, 238, 202, 246, 254, 259, 255, 256, 264, 257, 258, 247, 251, 252, 260, 261, 263, 265, 266, 268, 267, 269, 270, 271, 272, 273, 274, 275, 278, 276, 277, 279, 280, 281, 282, 283, 284, 286, 288, 290, 285, 287, 289, 291, 292, 293, 294, 295, 296, 67, 297, 298, 300, 302, 304, 306, 79, 81, 249, 84, 75, 244, 299, 301, 96, 243, 0, 0, 0, 0, 0, 0, 303, 305, 307, }; short yycheck[] = { 101, 102, 269, 271, 105, 106, 270, 108, 109, 258, 259, 259, 111, 270, 113, 270, 264, 271, 267, 270, 268, 122, 331, 13, 125, 126, 16, 17, 129, 19, 131, 132, 7, 8, 9, 10, 11, 27, 28, 14, 15, 31, 271, 18, 270, 20, 21, 22, 270, 24, 270, 271, 304, 331, 29, 30, 270, 32, 33, 34, 35, 36, 270, 271, 271, 332, 270, 319, 332, 321, 322, 270, 271, 270, 271, 270, 257, 329, 330, 260, 270, 262, 263, 261, 270, 271, 270, 265, 266, 271, 270, 271, 331, 270, 69, 270, 271, 270, 271, 270, 271, 270, 271, 270, 271, 270, 270, 270, 270, 270, 270, 270, 270, 331, 271, 271, 270, 332, 271, 270, 270, 270, 223, 271, 270, 331, 270, 117, 271, 271, 332, 331, 320, 271, 332, 256, 332, 271, 332, 331, 271, 116, 331, 118, 271, 270, 272, 271, 270, 272, 266, 271, 273, 274, 271, 256, 277, 278, 279, 280, 281, 282, 283, 284, 285, 271, 271, 271, 271, 271, 38, 271, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 271, 312, 313, 314, 315, 316, 317, 318, 271, 271, 271, 271, 323, 324, 325, 326, 327, 270, 329, 330, 270, 272, 331, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 332, 332, 271, 270, 272, 271, 270, 272, 271, 271, 332, 332, 332, 332, 332, 332, 271, 271, 332, 272, 332, 272, 272, 332, 332, 272, 272, 272, 332, 332, 332, 272, 332, 272, 332, 272, 272, 272, 272, 332, 332, 332, 332, 272, 332, 272, 332, 272, 271, 332, 272, 272, 272, 272, 272, 271, 271, 222, 271, 271, 201, 332, 332, 320, 200, -1, -1, -1, -1, -1, -1, 332, 332, 332, }; #define YYFINAL 1 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 332 #if YYDEBUG char *yyname[] = { "end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"A","B","C","E","F","I","L","N", "P","R","S","T","ALL","SP","CRLF","COMMA","USER","PASS","ACCT","REIN","QUIT", "PORT","PASV","TYPE","STRU","MODE","RETR","STOR","APPE","MLFL","MAIL","MSND", "MSOM","MSAM","MRSQ","MRCP","ALLO","REST","RNFR","RNTO","ABOR","DELE","CWD", "LIST","NLST","SITE","STAT","HELP","NOOP","MKD","RMD","PWD","CDUP","STOU", "SMNT","SYST","SIZE","MDTM","LPRT","LPSV","EPRT","EPSV","UMASK","IDLE","CHMOD", "MDFIVE","FEAT","OPTS","AUTH","PROT","PBSZ","LEXERR","NOTIMPL","SYNTERR", "STRING","NUMBER", }; char *yyrule[] = { "$accept : cmd_list", "cmd_list :", "cmd_list : cmd_list cmd", "cmd_list : cmd_list rcmd", "cmd : AUTH SP auth_type CRLF", "cmd : PBSZ SP buffer_size CRLF", "cmd : PROT check_login_apbu SP protection_level CRLF", "cmd : USER SP username CRLF", "cmd : PASS SP password CRLF", "cmd : PASS CRLF", "cmd : PORT check_login SP host_port CRLF", "cmd : LPRT check_login SP host_long_port CRLF", "cmd : EPRT check_login_epsv SP STRING CRLF", "cmd : PASV check_login CRLF", "cmd : LPSV check_login CRLF", "cmd : EPSV check_login_epsv SP NUMBER CRLF", "cmd : EPSV check_login_epsv SP ALL CRLF", "cmd : EPSV check_login_epsv CRLF", "cmd : TYPE check_login SP type_code CRLF", "cmd : STRU check_login SP struct_code CRLF", "cmd : MODE check_login SP mode_code CRLF", "cmd : ALLO check_login SP NUMBER CRLF", "cmd : ALLO check_login SP NUMBER SP R SP NUMBER CRLF", "cmd : RETR check_login SP pathname CRLF", "cmd : STOR check_login_ro SP pathname CRLF", "cmd : APPE check_login_ro SP pathname CRLF", "cmd : NLST check_login CRLF", "cmd : NLST check_login SP pathstring CRLF", "cmd : LIST check_login CRLF", "cmd : LIST check_login SP pathstring CRLF", "cmd : STAT check_login SP pathname CRLF", "cmd : STAT check_login CRLF", "cmd : DELE check_login_ro SP pathname CRLF", "cmd : RNTO check_login_ro SP pathname CRLF", "cmd : ABOR check_login CRLF", "cmd : CWD check_login CRLF", "cmd : CWD check_login SP pathname CRLF", "cmd : HELP CRLF", "cmd : HELP SP STRING CRLF", "cmd : NOOP CRLF", "cmd : MKD check_login_ro SP pathname CRLF", "cmd : RMD check_login_ro SP pathname CRLF", "cmd : PWD check_login CRLF", "cmd : CDUP check_login CRLF", "cmd : SITE SP HELP CRLF", "cmd : SITE SP HELP SP STRING CRLF", "cmd : SITE SP MDFIVE check_login SP pathname CRLF", "cmd : SITE SP UMASK check_login CRLF", "cmd : SITE SP UMASK check_login SP octal_number CRLF", "cmd : SITE SP CHMOD check_login_ro SP octal_number SP pathname CRLF", "cmd : SITE SP check_login IDLE CRLF", "cmd : SITE SP check_login IDLE SP NUMBER CRLF", "cmd : STOU check_login_ro SP pathname CRLF", "cmd : SYST check_login CRLF", "cmd : SIZE check_login SP pathname CRLF", "cmd : MDTM check_login SP pathname CRLF", "cmd : FEAT CRLF", "cmd : OPTS SP STRING CRLF", "cmd : QUIT CRLF", "cmd : NOTIMPL", "cmd : SITE SP NOTIMPL", "cmd : SYNTERR", "cmd : SITE SP SYNTERR", "cmd : error", "rcmd : RNFR check_login_ro SP pathname CRLF", "rcmd : REST check_login SP NUMBER CRLF", "username : STRING", "password :", "password : STRING", "auth_type : STRING", "protection_level : STRING", "byte_size : NUMBER", "buffer_size : NUMBER", "host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER", "host_long_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER", "host_long_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER", "form_code : N", "form_code : T", "form_code : C", "type_code : A", "type_code : A SP form_code", "type_code : E", "type_code : E SP form_code", "type_code : I", "type_code : L", "type_code : L SP byte_size", "type_code : L byte_size", "struct_code : F", "struct_code : R", "struct_code : P", "mode_code : S", "mode_code : B", "mode_code : C", "pathname : pathstring", "pathstring : STRING", "octal_number : NUMBER", "check_login :", "check_login_epsv :", "check_login_ro :", "check_login_apbu :", }; #endif #ifdef YYSTACKSIZE #undef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 10000 #define YYMAXDEPTH 10000 #endif #endif #define YYINITSTACKSIZE 200 int yydebug; int yynerrs; int yyerrflag; int yychar; short *yyssp; YYSTYPE *yyvsp; YYSTYPE yyval; YYSTYPE yylval; short *yyss; short *yysslim; YYSTYPE *yyvs; int yystacksize; #line 1252 "ftpcmd.y" #define CMD 0 /* beginning of command */ #define ARGS 1 /* expect miscellaneous arguments */ #define STR1 2 /* expect SP followed by STRING */ #define STR2 3 /* expect STRING */ #define OSTR 4 /* optional SP then STRING */ #define ZSTR1 5 /* optional SP then optional STRING */ #define ZSTR2 6 /* optional STRING after SP */ #define SITECMD 7 /* SITE command */ #define NSTR 8 /* Number followed by a string */ #define NOARGS 9 /* No arguments allowed */ #define OARGS 10 /* optional miscellaneous arguments */ #define MAXGLOBARGS 1000 #define MAXASIZE 10240 /* Deny ASCII SIZE on files larger than that */ struct tab { char *name; short token; short state; short implemented; /* 1 if command is implemented */ char *help; }; struct tab cmdtab[] = { /* In order defined in related documents */ /* RFC 959 */ { "USER", USER, STR1, 1, " username" }, { "PASS", PASS, ZSTR1, 1, "[ [password]]" }, { "ACCT", ACCT, STR1, 0, "(specify account)" }, { "CWD", CWD, OSTR, 1, "[ directory-name ]" }, { "CDUP", CDUP, NOARGS, 1, "(change to parent directory)" }, { "SMNT", SMNT, ARGS, 0, "(structure mount)" }, { "REIN", REIN, NOARGS, 0, "(reinitialize server state)" }, { "QUIT", QUIT, NOARGS, 1, "(terminate service)" }, { "PORT", PORT, ARGS, 1, " b0, b1, b2, b3, b4, b5" }, { "PASV", PASV, NOARGS, 1, "(set server in passive mode)" }, { "TYPE", TYPE, ARGS, 1, " { A | E | I | L }" }, { "STRU", STRU, ARGS, 1, "(specify file structure)" }, { "MODE", MODE, ARGS, 1, "(specify transfer mode)" }, { "RETR", RETR, STR1, 1, " file-name" }, { "STOR", STOR, STR1, 1, " file-name" }, { "STOU", STOU, STR1, 1, " file-name" }, { "APPE", APPE, STR1, 1, " file-name" }, { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" }, { "REST", REST, ARGS, 1, " offset (restart command)" }, { "RNFR", RNFR, STR1, 1, " file-name" }, { "RNTO", RNTO, STR1, 1, " file-name" }, { "ABOR", ABOR, NOARGS, 1, "(abort operation)" }, { "DELE", DELE, STR1, 1, " file-name" }, { "RMD", RMD, STR1, 1, " path-name" }, { "MKD", MKD, STR1, 1, " path-name" }, { "PWD", PWD, NOARGS, 1, "(return current directory)" }, { "LIST", LIST, OSTR, 1, "[ path-name ]" }, { "NLST", NLST, OSTR, 1, "[ path-name ]" }, { "SITE", SITE, SITECMD, 1, "site-cmd [ arguments ]" }, { "SYST", SYST, NOARGS, 1, "(get type of operating system)" }, { "STAT", STAT, OSTR, 1, "[ path-name ]" }, { "HELP", HELP, OSTR, 1, "[ ]" }, { "NOOP", NOOP, NOARGS, 1, "" }, /* RFC 1639 */ { "LPRT", LPRT, ARGS, 1, " af, hal, h1, h2, h3,..., pal, p1, p2..." }, { "LPSV", LPSV, NOARGS, 1, "(set server in passive mode)" }, /* RFC 2428 */ { "EPRT", EPRT, STR1, 1, " |af|addr|port|" }, { "EPSV", EPSV, OARGS, 1, "[ af|ALL]" }, /* obsoleted commands (RFC 751, ...) */ { "MLFL", MLFL, OSTR, 0, "(mail file)" }, { "MAIL", MAIL, OSTR, 0, "(mail to user)" }, { "MSND", MSND, OSTR, 0, "(mail send to terminal)" }, { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" }, { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" }, { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" }, { "MRCP", MRCP, STR1, 0, "(mail recipient)" }, { "XCWD", CWD, OSTR, 1, "[ directory-name ]" }, { "XMKD", MKD, STR1, 1, " path-name" }, { "XRMD", RMD, STR1, 1, " path-name" }, { "XPWD", PWD, NOARGS, 1, "(return current directory)" }, { "XCUP", CDUP, NOARGS, 1, "(change to parent directory)" }, /* RFC 3659 */ { "SIZE", SIZE, STR1, 1, " path-name" }, { "MDTM", MDTM, STR1, 1, " path-name" }, /* RFC 2389 */ { "FEAT", FEAT, NOARGS, 1, "(return list of supported extensions)" }, { "OPTS", OPTS, STR1, 1, " command [ options ]" }, /* RFC 2228 */ #ifdef USE_SSL { "AUTH", AUTH, STR1, 1, " mechanism-name" }, { "PBSZ", PBSZ, ARGS, 1, " decimal-integer" }, { "PROT", PROT, STR1, 1, " prot-code" }, #else /* !USE_SSL */ { "AUTH", AUTH, STR1, 0, " mechanism-name" }, { "PBSZ", PBSZ, ARGS, 0, " decimal-integer" }, { "PROT", PROT, STR1, 0, " prot-code" }, #endif /* USE_SSL */ { NULL, 0, 0, 0, 0 } }; struct tab sitetab[] = { #ifdef USE_MD5 { "MD5", MDFIVE, STR1, 1, " file-name" }, #else /* !USE_MD5 */ { "MD5", MDFIVE, STR1, 0, " file-name" }, #endif /* USE_MD5 */ { "UMASK", UMASK, OARGS, 1, "[ umask ]" }, { "IDLE", IDLE, OARGS, 1, "[ maximum-idle-time ]" }, { "CHMOD", CHMOD, NSTR, 1, " mode file-name" }, { "HELP", HELP, OSTR, 1, "[ ]" }, { NULL, 0, 0, 0, 0 } }; static char *copy(char *); static char *expglob(char *); static char *exptilde(char *); static void help(struct tab *, char *); static struct tab * lookup(struct tab *, char *); static void opts(char *); static int port_check(const char *); #ifdef INET6 static int port_check_v6(const char *); #endif static void sizecmd(char *); static void toolong(int); #ifdef INET6 static void v4map_data_dest(void); #endif static int yylex(void); static struct tab * lookup(struct tab *p, char *cmd) { for (; p->name != NULL; p++) if (strcasecmp(cmd, p->name) == 0) return (p); return (0); } #include /* * getline - a hacked up version of fgets to ignore TELNET escape codes. */ char * getline(char *s, int n, FILE *iop) { int c; register char *cs; sigset_t sset, osset; char buf[16]; cs = s; /* tmpline may contain saved command from urgent mode interruption */ for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) { *cs++ = tmpline[c]; if (tmpline[c] == '\n') { *cs++ = '\0'; if (ftpdebug) syslog(LOG_DEBUG, "command: %s", s); tmpline[0] = '\0'; return(s); } if (c == 0) tmpline[0] = '\0'; } /* SIGURG would interrupt stdio if not blocked during the read loop */ sigemptyset(&sset); sigaddset(&sset, SIGURG); #ifdef USE_SSL /* "pseudo-OOB" with SSL */ sigaddset(&sset, SIGIO); #endif /*USE_SSL*/ sigprocmask(SIG_BLOCK, &sset, &osset); while ((c = GETC(iop)) != EOF) { c &= 0377; if (c == IAC) { if ((c = GETC(iop)) == EOF) goto got_eof; c &= 0377; switch (c) { case WILL: case WONT: if ((c = GETC(iop)) == EOF) goto got_eof; snprintf(buf, sizeof(buf), "%c%c%c", IAC, DONT, 0377&c); #ifdef USE_SSL if (ssl_active_flag) ssl_write(ssl_con, buf, strlen(buf)); else #endif /* USE_SSL */ fwrite(buf, strlen(buf), 1, stdout); (void) FFLUSH(stdout); continue; case DO: case DONT: if ((c = GETC(iop)) == EOF) goto got_eof; snprintf(buf, sizeof(buf), "%c%c%c", IAC, WONT, 0377&c); #ifdef USE_SSL if (ssl_active_flag) ssl_write(ssl_con, buf, strlen(buf)); else #endif /* USE_SSL */ fwrite(buf, strlen(buf), 1, stdout); (void) FFLUSH(stdout); continue; case IAC: break; default: continue; /* ignore command */ } } *cs++ = c; if (--n <= 0 || c == '\n') break; } got_eof: sigprocmask(SIG_SETMASK, &osset, NULL); if (c == EOF && cs == s) return (NULL); *cs++ = '\0'; if (ftpdebug) { if (!guest && strncasecmp("pass ", s, 5) == 0) { /* Don't syslog passwords */ syslog(LOG_DEBUG, "command: %.5s ???", s); } else { register char *cp; register int len; /* Don't syslog trailing CR-LF */ len = strlen(s); cp = s + len - 1; while (cp >= s && (*cp == '\n' || *cp == '\r')) { --cp; --len; } syslog(LOG_DEBUG, "command: %.*s", len, s); } } return (s); } static void toolong(int signo) { reply(421, "Timeout (%d seconds): closing control connection.", timeout); if (logging) syslog(LOG_INFO, "User %s timed out after %d seconds", (pw ? pw -> pw_name : "unknown"), timeout); dologout(1); } /* * Basic syntax checking for informational purposes. * arguments: * cmd - an FTP command presented by the item of the FTP command table; * cbuf - the buffer (with removed '\r' symbols), which contains the FTP * command code and the argument field. * cpos - the position (starting from 0) of the symbol which is next * after the end of the command code. * return: * 0 - syntax error is found. * 1 - in other cases. * notes: * This function checks only the requirement of the arguments and doesn't * perform the verification of the syntax of the argument field. */ static int check_syntax(struct tab *cmd, char *cbuf, size_t cpos) { if ( (cmd->state == NOARGS && cbuf[cpos] != '\n') || (cmd->state != NOARGS && cmd->state != OARGS && cmd->state != OSTR && cmd->state != ZSTR1 && cbuf[cpos] == '\n') ) return 0; return 1; } static int yylex(void) { static int cpos; char *cp, *cp2; struct tab *p; int n; char c; for (;;) { switch (state) { case CMD: (void) signal(SIGALRM, toolong); (void) alarm(timeout); if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) { reply(221, "You could at least say goodbye."); dologout(0); } (void) alarm(0); #ifdef SETPROCTITLE if (strncasecmp(cbuf, "PASS", 4) != 0) setproctitle("%s: %s", proctitle, cbuf); #endif /* SETPROCTITLE */ if ((cp = strchr(cbuf, '\r'))) { *cp++ = '\n'; *cp = '\0'; } if ((cp = strpbrk(cbuf, " \n"))) cpos = cp - cbuf; if (cpos == 0) cpos = 4; c = cbuf[cpos]; cbuf[cpos] = '\0'; upper(cbuf); p = lookup(cmdtab, cbuf); cbuf[cpos] = c; if (p != 0) { yylval.s = p->name; if (!p->implemented) return (NOTIMPL); /* state remains CMD */ if ( !check_syntax(p, cbuf, cpos) ) { return (SYNTERR); /* state remains CMD */ } state = p->state; return (p->token); } break; case SITECMD: if (cbuf[cpos] == ' ') { cpos++; return (SP); } cp = &cbuf[cpos]; if ((cp2 = strpbrk(cp, " \n"))) cpos = cp2 - cbuf; c = cbuf[cpos]; cbuf[cpos] = '\0'; upper(cp); p = lookup(sitetab, cp); cbuf[cpos] = c; if (guest == 0 && p != 0) { yylval.s = p->name; if (!p->implemented) { state = CMD; return (NOTIMPL); } if ( !check_syntax(p, cbuf, cpos) ) { state = CMD; return (SYNTERR); } state = p->state; return (p->token); } state = CMD; break; case ZSTR1: case OSTR: if (cbuf[cpos] == '\n') { state = CMD; return (CRLF); } /* FALLTHROUGH */ case STR1: dostr1: if (cbuf[cpos] == ' ') { cpos++; state = state == OSTR ? STR2 : state+1; return (SP); } break; case ZSTR2: if (cbuf[cpos] == '\n') { state = CMD; return (CRLF); } /* FALLTHROUGH */ case STR2: cp = &cbuf[cpos]; n = strlen(cp); cpos += n - 1; /* * Make sure the string is nonempty and \n terminated. */ if (n > 1 && cbuf[cpos] == '\n') { cbuf[cpos] = '\0'; yylval.s = copy(cp); cbuf[cpos] = '\n'; state = ARGS; return (STRING); } break; case NSTR: if (cbuf[cpos] == ' ') { cpos++; return (SP); } if (isdigit(cbuf[cpos])) { cp = &cbuf[cpos]; while (isdigit(cbuf[++cpos])) ; c = cbuf[cpos]; cbuf[cpos] = '\0'; yylval.u.i = atoi(cp); cbuf[cpos] = c; state = STR1; return (NUMBER); } state = STR1; goto dostr1; case OARGS: case ARGS: if (isdigit(cbuf[cpos])) { cp = &cbuf[cpos]; while (isdigit(cbuf[++cpos])) ; c = cbuf[cpos]; cbuf[cpos] = '\0'; yylval.u.i = atoi(cp); yylval.u.o = strtoull(cp, NULL, 10); cbuf[cpos] = c; return (NUMBER); } if (strncasecmp(&cbuf[cpos], "ALL", 3) == 0 && !isalnum(cbuf[cpos + 3])) { cpos += 3; return ALL; } switch (cbuf[cpos++]) { case '\n': state = CMD; return (CRLF); case ' ': return (SP); case ',': return (COMMA); case 'A': case 'a': return (A); case 'B': case 'b': return (B); case 'C': case 'c': return (C); case 'E': case 'e': return (E); case 'F': case 'f': return (F); case 'I': case 'i': return (I); case 'L': case 'l': return (L); case 'N': case 'n': return (N); case 'P': case 'p': return (P); case 'R': case 'r': return (R); case 'S': case 's': return (S); case 'T': case 't': return (T); } break; case NOARGS: if (cbuf[cpos] == '\n') { state = CMD; return (CRLF); } break; default: fatalerror("Unknown state in scanner."); } state = CMD; return (LEXERR); } } void upper(char *s) { while (*s != '\0') { if (islower(*s)) *s = toupper(*s); s++; } } static char * copy(char *s) { char *p; p = malloc(strlen(s) + 1); if (p == NULL) fatalerror("Ran out of memory."); (void) strcpy(p, s); return (p); } static void help(struct tab *ctab, char *s) { struct tab *c; int width, NCMDS; char *type; if (ctab == sitetab) type = "SITE "; else type = ""; width = 0, NCMDS = 0; for (c = ctab; c->name != NULL; c++) { int len = strlen(c->name); if (len > width) width = len; NCMDS++; } width = (width + 8) &~ 7; if (s == 0) { int i, j, w; int columns, lines; lreply(214, "The following %scommands are recognized %s.", type, "(* =>'s unimplemented)"); columns = 76 / width; if (columns == 0) columns = 1; lines = (NCMDS + columns - 1) / columns; for (i = 0; i < lines; i++) { PRINTF(" "); for (j = 0; j < columns; j++) { c = ctab + j * lines + i; PRINTF("%s%c", c->name, c->implemented ? ' ' : '*'); if (c + lines >= &ctab[NCMDS]) break; w = strlen(c->name) + 1; while (w < width) { PRINTF(" "); w++; } } PRINTF("\r\n"); } (void) FFLUSH(stdout); if (hostinfo) reply(214, "Direct comments to ftp-bugs@%s.", hostname); else reply(214, "End."); return; } upper(s); c = lookup(ctab, s); if (c == NULL) { reply(502, "Unknown command %s.", s); return; } if (c->implemented) reply(214, "Syntax: %s%s %s", type, c->name, c->help); else reply(214, "%s%-*s\t%s; unimplemented.", type, width, c->name, c->help); } static void sizecmd(char *filename) { switch (type) { case TYPE_L: case TYPE_I: { struct stat stbuf; if (stat(filename, &stbuf) < 0) perror_reply(550, filename); else if (!S_ISREG(stbuf.st_mode)) reply(550, "%s: not a plain file.", filename); else reply(213, "%jd", (intmax_t)stbuf.st_size); break; } case TYPE_A: { FILE *fin; int c; off_t count; struct stat stbuf; fin = fopen(filename, "r"); if (fin == NULL) { perror_reply(550, filename); return; } if (fstat(fileno(fin), &stbuf) < 0) { perror_reply(550, filename); (void) fclose(fin); return; } else if (!S_ISREG(stbuf.st_mode)) { reply(550, "%s: not a plain file.", filename); (void) fclose(fin); return; } else if (stbuf.st_size > MAXASIZE) { reply(550, "%s: too large for type A SIZE.", filename); (void) fclose(fin); return; } count = 0; while((c=getc(fin)) != EOF) { if (c == '\n') /* will get expanded to \r\n */ count++; count++; } (void) fclose(fin); reply(213, "%jd", (intmax_t)count); break; } default: reply(504, "SIZE not implemented for type %s.", typenames[type]); } } /* Return 1, if port check is done. Return 0, if not yet. */ static int port_check(const char *pcmd) { if (his_addr.su_family == AF_INET) { if (data_dest.su_family != AF_INET) { usedefault = 1; reply(500, "Invalid address rejected."); return 1; } if (ftpdparanoid && ((ntohs(data_dest.su_port) < IPPORT_RESERVED) || memcmp(&data_dest.su_sin.sin_addr, &his_addr.su_sin.sin_addr, sizeof(data_dest.su_sin.sin_addr)))) { usedefault = 1; reply(500, "Illegal PORT range rejected."); } else { usedefault = 0; if (pdata >= 0) { (void) close(pdata); pdata = -1; } reply(200, "%s command successful.", pcmd); } return 1; } return 0; } static int check_login1(void) { if (logged_in) return 1; else { reply(530, "Please login with USER and PASS."); return 0; } } /* * Replace leading "~user" in a pathname by the user's login directory. * Returned string will be in a freshly malloced buffer unless it's NULL. */ static char * exptilde(char *s) { char *p, *q; char *path, *user; struct passwd *ppw; if ((p = strdup(s)) == NULL) return (NULL); if (*p != '~') return (p); user = p + 1; /* skip tilde */ if ((path = strchr(p, '/')) != NULL) *(path++) = '\0'; /* separate ~user from the rest of path */ if (*user == '\0') /* no user specified, use the current user */ user = pw->pw_name; /* read passwd even for the current user since we may be chrooted */ if ((ppw = getpwnam(user)) != NULL) { /* user found, substitute login directory for ~user */ if (path) asprintf(&q, "%s/%s", ppw->pw_dir, path); else q = strdup(ppw->pw_dir); free(p); p = q; } else { /* user not found, undo the damage */ if (path) path[-1] = '/'; } return (p); } /* * Expand glob(3) patterns possibly present in a pathname. * Avoid expanding to a pathname including '\r' or '\n' in order to * not disrupt the FTP protocol. * The expansion found must be unique. * Return the result as a malloced string, or NULL if an error occured. * * Problem: this production is used for all pathname * processing, but only gives a 550 error reply. * This is a valid reply in some cases but not in others. */ static char * expglob(char *s) { char *p, **pp, *rval; int flags = GLOB_BRACE | GLOB_NOCHECK; int n; glob_t gl; memset(&gl, 0, sizeof(gl)); flags |= GLOB_LIMIT; gl.gl_matchc = MAXGLOBARGS; #ifdef LINUX /* Linux port */ if (bsdglob(s, flags, NULL, &gl) == 0 && gl.gl_pathc != 0) { #else /* BSD source */ if (glob(s, flags, NULL, &gl) == 0 && gl.gl_pathc != 0) { #endif /* BSD source */ for (pp = gl.gl_pathv, p = NULL, n = 0; *pp; pp++) if (*(*pp + strcspn(*pp, "\r\n")) == '\0') { p = *pp; n++; } if (n == 0) rval = strdup(s); else if (n == 1) rval = strdup(p); else { reply(550, "Wildcard is ambiguous."); rval = NULL; } } else { reply(550, "Wildcard expansion error."); rval = NULL; } globfree(&gl); return (rval); } #ifdef INET6 /* Return 1, if port check is done. Return 0, if not yet. */ static int port_check_v6(const char *pcmd) { if (his_addr.su_family == AF_INET6) { if (IN6_IS_ADDR_V4MAPPED(&his_addr.su_sin6.sin6_addr)) /* Convert data_dest into v4 mapped sockaddr.*/ v4map_data_dest(); if (data_dest.su_family != AF_INET6) { usedefault = 1; reply(500, "Invalid address rejected."); return 1; } if (ftpdparanoid && ((ntohs(data_dest.su_port) < IPPORT_RESERVED) || memcmp(&data_dest.su_sin6.sin6_addr, &his_addr.su_sin6.sin6_addr, sizeof(data_dest.su_sin6.sin6_addr)))) { usedefault = 1; reply(500, "Illegal PORT range rejected."); } else { usedefault = 0; if (pdata >= 0) { (void) close(pdata); pdata = -1; } reply(200, "%s command successful.", pcmd); } return 1; } return 0; } static void v4map_data_dest(void) { struct in_addr savedaddr; int savedport; if (data_dest.su_family != AF_INET) { usedefault = 1; reply(500, "Invalid address rejected."); return; } savedaddr = data_dest.su_sin.sin_addr; savedport = data_dest.su_port; memset(&data_dest, 0, sizeof(data_dest)); #ifndef LINUX /* BSD source */ data_dest.su_sin6.sin6_len = sizeof(struct sockaddr_in6); #endif data_dest.su_sin6.sin6_family = AF_INET6; data_dest.su_sin6.sin6_port = savedport; memset((caddr_t)&data_dest.su_sin6.sin6_addr.s6_addr[10], 0xff, 2); memcpy((caddr_t)&data_dest.su_sin6.sin6_addr.s6_addr[12], (caddr_t)&savedaddr, sizeof(savedaddr)); } #endif /* * An implementation of the OPTS command defined in RFC 2389. * arguments: * command - the string with next syntax: * command-name [ SP command-options ] * return: * none * notes: * command-name: any FTP command which allows option setting; * command-options: format specified by individual FTP command. */ void opts(char *command) { struct tab *c; char *s; if ((s = strchr(command, ' ')) != NULL) *s++ = '\0'; c = lookup(cmdtab, command); /* * Simple cases. */ /* Check if the command is known. */ if (c == NULL) { reply(500, "%s: command not understood.", command); return; } /* Check if the command is implemented. */ if (!c->implemented) { reply(502, "%s command not implemented.", c->name); return; } /* * The commands for whose the OPTS command is defined. */ /* none at this moment */ /* * Default case. */ reply(501, "OPTS command is not defined for %s.", c->name); } #line 1441 "ftpcmd.c" /* allocate initial stack or double stack size, up to YYMAXDEPTH */ int yyparse __P((void)); static int yygrowstack __P((void)); static int yygrowstack() { int newsize, i; short *newss; YYSTYPE *newvs; if ((newsize = yystacksize) == 0) newsize = YYINITSTACKSIZE; else if (newsize >= YYMAXDEPTH) return -1; else if ((newsize *= 2) > YYMAXDEPTH) newsize = YYMAXDEPTH; i = yyssp - yyss; if ((newss = (short *)realloc(yyss, newsize * sizeof *newss)) == NULL) return -1; yyss = newss; yyssp = newss + i; if ((newvs = (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs)) == NULL) return -1; yyvs = newvs; yyvsp = newvs + i; yystacksize = newsize; yysslim = yyss + newsize - 1; return 0; } #define YYABORT goto yyabort #define YYREJECT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int yyparse() { int yym, yyn, yystate; #if YYDEBUG char *yys; if ((yys = getenv("YYDEBUG")) != NULL) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn - '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = (-1); if (yyss == NULL && yygrowstack()) goto yyoverflow; yyssp = yyss; yyvsp = yyvs; *yyssp = yystate = 0; yyloop: if ((yyn = yydefred[yystate]) != 0) goto yyreduce; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("%sdebug: state %d, reading %d (%s)\n", YYPREFIX, yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("%sdebug: state %d, shifting to state %d\n", YYPREFIX, yystate, yytable[yyn]); #endif if (yyssp >= yysslim && yygrowstack()) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; yychar = (-1); if (yyerrflag > 0) --yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; goto yynewerror; yynewerror: yyerror("syntax error"); goto yyerrlab; yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("%sdebug: state %d, error recovery shifting\ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]); #endif if (yyssp >= yysslim && yygrowstack()) { goto yyoverflow; } *++yyssp = yystate = yytable[yyn]; *++yyvsp = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("%sdebug: error recovery discarding state %d\n", YYPREFIX, *yyssp); #endif if (yyssp <= yyss) goto yyabort; --yyssp; --yyvsp; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("%sdebug: state %d, error recovery discards token %d (%s)\n", YYPREFIX, yystate, yychar, yys); } #endif yychar = (-1); goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("%sdebug: state %d, reducing by rule %d (%s)\n", YYPREFIX, yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; yyval = yyvsp[1-yym]; switch (yyn) { case 2: #line 190 "ftpcmd.y" { if (fromname) free(fromname); fromname = NULL; restart_point = 0; } break; case 4: #line 201 "ftpcmd.y" { #ifdef USE_SSL /* Compatibility with early implementations of SSL upgrade. */ if (!strcasecmp(yyvsp[-1].s, "SSL") && (ssl_secure_flags & SSL_USE_COMPAT)) { reply(!ssl_uorc_flag ? 234 : 334, "AUTH SSL command successful."); /* Initialize the TLS/SSL session. */ ssl_compat_flag = 1; do_ssl_start(); ssl_encrypt_data = 1; /* Implementation of the FTP-TLS v12 IETF draft. */ } else if (!strcasecmp(yyvsp[-1].s, "TLS") && (ssl_secure_flags & SSL_USE_TLS)) { reply(234, "AUTH TLS command successful."); /* Initialize the TLS/SSL session. */ do_ssl_start(); } else { reply(504, "AUTH: security mechanism '%s' not supported.", yyvsp[-1].s); } if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); #endif /* USE_SSL */ } break; case 5: #line 231 "ftpcmd.y" { #ifdef USE_SSL if (ssl_active_flag) { reply(200, "PBSZ command successful (PBSZ=0)."); PBSZ_used_flag = 1; } else { reply(503, "Use AUTH command first."); } #endif /* USE_SSL */ } break; case 6: #line 242 "ftpcmd.y" { #ifdef USE_SSL if(yyvsp[-3].u.i) { if (ssl_compat_flag) { reply(504, "PROT command not available in FTP-SSL " "compatibility mode."); goto prot_end; } else if (ssl_active_flag && PBSZ_used_flag) { if (!strcasecmp(yyvsp[-1].s, "C")) { ssl_encrypt_data = 0; } else if (!strcasecmp(yyvsp[-1].s, "P")) { ssl_encrypt_data = 1; } else { reply(504, "Protection level '%s' not supported.", yyvsp[-1].s); goto prot_end; } reply(200, "Protection level set to %s.", ssl_encrypt_data ? "Private" : "Clear"); if (logging) syslog(LOG_NOTICE, "data connection protection level set to %s", ssl_encrypt_data ? "Private" : "Clear"); } else { reply(503, "Use AUTH and PBSZ commands first."); goto prot_end; } } prot_end: if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); #endif /* USE_SSL */ } break; case 7: #line 278 "ftpcmd.y" { #ifdef USE_SSL if (!(ssl_secure_flags & SSL_USE_NONSECURE) && !ssl_active_flag) { reply(504, "TLS/SSL protection required."); goto user_end; } #endif /* USE_SSL */ user(yyvsp[-1].s); user_end: free(yyvsp[-1].s); } break; case 8: #line 291 "ftpcmd.y" { #ifdef USE_SSL if (!(ssl_secure_flags & SSL_USE_NONSECURE) && !ssl_active_flag) { reply(504, "TLS/SSL protection required."); goto pass_end; } #endif /* USE_SSL */ pass(yyvsp[-1].s); pass_end: free(yyvsp[-1].s); } break; case 9: #line 304 "ftpcmd.y" { #ifdef USE_SSL if (!(ssl_secure_flags & SSL_USE_NONSECURE) && !ssl_active_flag) { reply(504, "TLS/SSL protection required."); goto passnull_end; } #endif /* USE_SSL */ pass(""); passnull_end: ; } break; case 10: #line 317 "ftpcmd.y" { if (epsvall) { reply(501, "No PORT allowed after EPSV ALL."); goto port_done; } if (!yyvsp[-3].u.i) goto port_done; if (port_check("PORT") == 1) goto port_done; #ifdef INET6 if ((his_addr.su_family != AF_INET6 || !IN6_IS_ADDR_V4MAPPED(&his_addr.su_sin6.sin6_addr))) { /* shoud never happen */ usedefault = 1; reply(500, "Invalid address rejected."); goto port_done; } port_check_v6("pcmd"); #endif port_done: ; } break; case 11: #line 340 "ftpcmd.y" { if (epsvall) { reply(501, "No LPRT allowed after EPSV ALL."); goto lprt_done; } if (!yyvsp[-3].u.i) goto lprt_done; if (port_check("LPRT") == 1) goto lprt_done; #ifdef INET6 if (his_addr.su_family != AF_INET6) { usedefault = 1; reply(500, "Invalid address rejected."); goto lprt_done; } if (port_check_v6("LPRT") == 1) goto lprt_done; #endif lprt_done: ; } break; case 12: #line 362 "ftpcmd.y" { char delim; char *tmp = NULL; char *p, *q; char *result[3]; struct addrinfo hints; struct addrinfo *res; int i; if (epsvall) { reply(501, "No EPRT allowed after EPSV ALL."); goto eprt_done; } if (!yyvsp[-3].u.i) goto eprt_done; memset(&data_dest, 0, sizeof(data_dest)); tmp = strdup(yyvsp[-1].s); if (ftpdebug) syslog(LOG_DEBUG, "%s", tmp); if (!tmp) { fatalerror("not enough core"); /*NOTREACHED*/ } p = tmp; delim = p[0]; p++; memset(result, 0, sizeof(result)); for (i = 0; i < 3; i++) { q = strchr(p, delim); if (!q || *q != delim) { parsefail: reply(500, "Invalid argument, rejected."); if (tmp) free(tmp); usedefault = 1; goto eprt_done; } *q++ = '\0'; result[i] = p; if (ftpdebug) syslog(LOG_DEBUG, "%d: %s", i, p); p = q; } /* some more sanity check */ p = result[0]; while (*p) { if (!isdigit(*p)) goto parsefail; p++; } p = result[2]; while (*p) { if (!isdigit(*p)) goto parsefail; p++; } /* grab address */ memset(&hints, 0, sizeof(hints)); if (atoi(result[0]) == 1) hints.ai_family = PF_INET; #ifdef INET6 else if (atoi(result[0]) == 2) hints.ai_family = PF_INET6; #endif else hints.ai_family = PF_UNSPEC; /*XXX*/ hints.ai_socktype = SOCK_STREAM; i = getaddrinfo(result[1], result[2], &hints, &res); if (i) goto parsefail; memcpy(&data_dest, res->ai_addr, res->ai_addrlen); #ifdef INET6 if (his_addr.su_family == AF_INET6 && data_dest.su_family == AF_INET6) { /* XXX more sanity checks! */ data_dest.su_sin6.sin6_scope_id = his_addr.su_sin6.sin6_scope_id; } #endif free(tmp); tmp = NULL; if (port_check("EPRT") == 1) goto eprt_done; #ifdef INET6 if (his_addr.su_family != AF_INET6) { usedefault = 1; reply(500, "Invalid address rejected."); goto eprt_done; } if (port_check_v6("EPRT") == 1) goto eprt_done; #endif eprt_done: free(yyvsp[-1].s); } break; case 13: #line 463 "ftpcmd.y" { if (epsvall) reply(501, "No PASV allowed after EPSV ALL."); else if (yyvsp[-1].u.i) passive(); } break; case 14: #line 470 "ftpcmd.y" { if (epsvall) reply(501, "No LPSV allowed after EPSV ALL."); else if (yyvsp[-1].u.i) long_passive("LPSV", PF_UNSPEC); } break; case 15: #line 477 "ftpcmd.y" { if (yyvsp[-3].u.i) { int pf; switch (yyvsp[-1].u.i) { case 1: pf = PF_INET; break; #ifdef INET6 case 2: pf = PF_INET6; break; #endif default: pf = -1; /*junk value*/ break; } long_passive("EPSV", pf); } } break; case 16: #line 497 "ftpcmd.y" { if (yyvsp[-3].u.i) { reply(200, "EPSV ALL command successful."); epsvall++; } } break; case 17: #line 504 "ftpcmd.y" { if (yyvsp[-1].u.i) long_passive("EPSV", PF_UNSPEC); } break; case 18: #line 509 "ftpcmd.y" { if (yyvsp[-3].u.i) { switch (cmd_type) { case TYPE_A: if (cmd_form == FORM_N) { reply(200, "Type set to A."); type = cmd_type; form = cmd_form; } else reply(504, "Form must be N."); break; case TYPE_E: reply(504, "Type E not implemented."); break; case TYPE_I: reply(200, "Type set to I."); type = cmd_type; break; case TYPE_L: #if CHAR_BIT == 8 if (cmd_bytesz == 8) { reply(200, "Type set to L (byte size 8)."); type = cmd_type; } else reply(504, "Byte size must be 8."); #else /* CHAR_BIT == 8 */ UNIMPLEMENTED for CHAR_BIT != 8 #endif /* CHAR_BIT == 8 */ } } } break; case 19: #line 546 "ftpcmd.y" { if (yyvsp[-3].u.i) { switch (yyvsp[-1].u.i) { case STRU_F: reply(200, "STRU F accepted."); break; default: reply(504, "Unimplemented STRU type."); } } } break; case 20: #line 560 "ftpcmd.y" { if (yyvsp[-3].u.i) { switch (yyvsp[-1].u.i) { case MODE_S: reply(200, "MODE S accepted."); break; default: reply(502, "Unimplemented MODE type."); } } } break; case 21: #line 574 "ftpcmd.y" { if (yyvsp[-3].u.i) { reply(202, "ALLO command ignored."); } } break; case 22: #line 580 "ftpcmd.y" { if (yyvsp[-7].u.i) { reply(202, "ALLO command ignored."); } } break; case 23: #line 586 "ftpcmd.y" { if (noretr || (guest && noguestretr)) reply(500, "RETR command disabled."); else if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) retrieve(NULL, yyvsp[-1].s); if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 24: #line 596 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) store(yyvsp[-1].s, "w", 0); if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 25: #line 603 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) store(yyvsp[-1].s, "a", 0); if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 26: #line 610 "ftpcmd.y" { if (yyvsp[-1].u.i) send_file_list("."); } break; case 27: #line 615 "ftpcmd.y" { if (yyvsp[-3].u.i) send_file_list(yyvsp[-1].s); free(yyvsp[-1].s); } break; case 28: #line 621 "ftpcmd.y" { if (yyvsp[-1].u.i) retrieve(_PATH_LS " -lgA", ""); } break; case 29: #line 626 "ftpcmd.y" { if (yyvsp[-3].u.i) retrieve(_PATH_LS " -lgA %s", yyvsp[-1].s); free(yyvsp[-1].s); } break; case 30: #line 632 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) statfilecmd(yyvsp[-1].s); if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 31: #line 639 "ftpcmd.y" { if (yyvsp[-1].u.i) { statcmd(); } } break; case 32: #line 645 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) delete(yyvsp[-1].s); if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 33: #line 652 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) { if (fromname) { renamecmd(fromname, yyvsp[-1].s); free(fromname); fromname = NULL; } else { reply(503, "Bad sequence of commands."); } } if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 34: #line 666 "ftpcmd.y" { if (yyvsp[-1].u.i) reply(225, "ABOR command successful."); } break; case 35: #line 671 "ftpcmd.y" { if (yyvsp[-1].u.i) { cwd(homedir); } } break; case 36: #line 677 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) cwd(yyvsp[-1].s); if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 37: #line 684 "ftpcmd.y" { help(cmdtab, NULL); } break; case 38: #line 688 "ftpcmd.y" { char *cp = yyvsp[-1].s; if (strncasecmp(cp, "SITE", 4) == 0) { cp = yyvsp[-1].s + 4; if (*cp == ' ') cp++; if (*cp) help(sitetab, cp); else help(sitetab, NULL); } else help(cmdtab, yyvsp[-1].s); free(yyvsp[-1].s); } break; case 39: #line 704 "ftpcmd.y" { reply(200, "NOOP command successful."); } break; case 40: #line 708 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) makedir(yyvsp[-1].s); if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 41: #line 715 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) removedir(yyvsp[-1].s); if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 42: #line 722 "ftpcmd.y" { if (yyvsp[-1].u.i) pwd(); } break; case 43: #line 727 "ftpcmd.y" { if (yyvsp[-1].u.i) cwd(".."); } break; case 44: #line 732 "ftpcmd.y" { help(sitetab, NULL); } break; case 45: #line 736 "ftpcmd.y" { help(sitetab, yyvsp[-1].s); free(yyvsp[-1].s); } break; case 46: #line 741 "ftpcmd.y" { #ifdef USE_MD5 char p[64], *q; if (yyvsp[-3].u.i && yyvsp[-1].s) { q = MD5File(yyvsp[-1].s, p); if (q != NULL) reply(200, "MD5(%s) = %s", yyvsp[-1].s, p); else perror_reply(550, yyvsp[-1].s); } if (yyvsp[-1].s) free(yyvsp[-1].s); #endif /* USE_MD5 */ } break; case 47: #line 757 "ftpcmd.y" { int oldmask; if (yyvsp[-1].u.i) { oldmask = umask(0); (void) umask(oldmask); reply(200, "Current UMASK is %03o.", oldmask); } } break; case 48: #line 767 "ftpcmd.y" { int oldmask; if (yyvsp[-3].u.i) { if ((yyvsp[-1].u.i == -1) || (yyvsp[-1].u.i > 0777)) { reply(501, "Bad UMASK value."); } else { oldmask = umask(yyvsp[-1].u.i); reply(200, "UMASK set to %03o (was %03o).", yyvsp[-1].u.i, oldmask); } } } break; case 49: #line 782 "ftpcmd.y" { if (yyvsp[-5].u.i && (yyvsp[-1].s != NULL)) { if ((yyvsp[-3].u.i == -1 ) || (yyvsp[-3].u.i > 0777)) reply(501, "Bad mode value."); else if (chmod(yyvsp[-1].s, yyvsp[-3].u.i) < 0) perror_reply(550, yyvsp[-1].s); else reply(200, "CHMOD command successful."); } if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 50: #line 795 "ftpcmd.y" { if (yyvsp[-2].u.i) reply(200, "Current IDLE time limit is %d seconds; max %d.", timeout, maxtimeout); } break; case 51: #line 802 "ftpcmd.y" { if (yyvsp[-4].u.i) { if (yyvsp[-1].u.i < 30 || yyvsp[-1].u.i > maxtimeout) { reply(501, "Maximum IDLE time must be between 30 and %d seconds.", maxtimeout); } else { timeout = yyvsp[-1].u.i; (void) alarm(timeout); reply(200, "Maximum IDLE time set to %d seconds.", timeout); } } } break; case 52: #line 818 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) store(yyvsp[-1].s, "w", 1); if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 53: #line 825 "ftpcmd.y" { if (yyvsp[-1].u.i) { if (hostinfo) #ifdef BSD reply(215, "UNIX Type: L%d Version: BSD-%d", CHAR_BIT, BSD); #else /* BSD */ reply(215, "UNIX Type: L%d", CHAR_BIT); #endif /* BSD */ else reply(215, "UNKNOWN Type: L%d", CHAR_BIT); } } break; case 54: #line 847 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) sizecmd(yyvsp[-1].s); if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 55: #line 864 "ftpcmd.y" { if (yyvsp[-3].u.i && yyvsp[-1].s != NULL) { struct stat stbuf; if (stat(yyvsp[-1].s, &stbuf) < 0) perror_reply(550, yyvsp[-1].s); else if (!S_ISREG(stbuf.st_mode)) { reply(550, "%s: not a plain file.", yyvsp[-1].s); } else { struct tm *t; t = gmtime(&stbuf.st_mtime); reply(213, "%04d%02d%02d%02d%02d%02d", 1900 + t->tm_year, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); } } if (yyvsp[-1].s != NULL) free(yyvsp[-1].s); } break; case 56: #line 885 "ftpcmd.y" { feat(); } break; case 57: #line 889 "ftpcmd.y" { opts(yyvsp[-1].s); free(yyvsp[-1].s); } break; case 58: #line 894 "ftpcmd.y" { reply(221, "Goodbye."); dologout(0); } break; case 59: #line 899 "ftpcmd.y" { nack(yyvsp[0].s); } break; case 60: #line 903 "ftpcmd.y" { char buf[64]; snprintf(buf, sizeof(buf), "SITE %s", yyvsp[0].s); nack(buf); } break; case 61: #line 909 "ftpcmd.y" { synterr(cbuf); } break; case 62: #line 913 "ftpcmd.y" { synterr(cbuf); } break; case 63: #line 917 "ftpcmd.y" { yyclearin; /* discard lookahead data */ yyerrok; /* clear error condition */ state = CMD; /* reset lexer state */ } break; case 64: #line 925 "ftpcmd.y" { restart_point = 0; if (yyvsp[-3].u.i && yyvsp[-1].s) { if (fromname) free(fromname); fromname = NULL; if (renamefrom(yyvsp[-1].s)) fromname = yyvsp[-1].s; else free(yyvsp[-1].s); } else if (yyvsp[-1].s) { free(yyvsp[-1].s); } } break; case 65: #line 940 "ftpcmd.y" { if (yyvsp[-3].u.i) { if (fromname) free(fromname); fromname = NULL; restart_point = yyvsp[-1].u.o; reply(350, "Restarting at %jd. %s", (intmax_t)restart_point, "Send STORE or RETRIEVE to initiate transfer."); } } break; case 67: #line 959 "ftpcmd.y" { yyval.s = (char *)calloc(1, sizeof(char)); } break; case 71: #line 976 "ftpcmd.y" { yyval.u.i = yyvsp[0].u.i; } break; case 72: #line 983 "ftpcmd.y" { yyval.u.i = yyvsp[0].u.i; } break; case 73: #line 991 "ftpcmd.y" { char *a, *p; #ifndef LINUX /* BSD source */ data_dest.su_len = sizeof(struct sockaddr_in); #endif data_dest.su_family = AF_INET; p = (char *)&data_dest.su_sin.sin_port; p[0] = yyvsp[-2].u.i; p[1] = yyvsp[0].u.i; a = (char *)&data_dest.su_sin.sin_addr; a[0] = yyvsp[-10].u.i; a[1] = yyvsp[-8].u.i; a[2] = yyvsp[-6].u.i; a[3] = yyvsp[-4].u.i; } break; case 74: #line 1012 "ftpcmd.y" { #ifdef INET6 char *a, *p; memset(&data_dest, 0, sizeof(data_dest)); #ifndef LINUX /* BSD source */ data_dest.su_len = sizeof(struct sockaddr_in6); #endif data_dest.su_family = AF_INET6; p = (char *)&data_dest.su_port; p[0] = yyvsp[-2].u.i; p[1] = yyvsp[0].u.i; a = (char *)&data_dest.su_sin6.sin6_addr; a[0] = yyvsp[-36].u.i; a[1] = yyvsp[-34].u.i; a[2] = yyvsp[-32].u.i; a[3] = yyvsp[-30].u.i; a[4] = yyvsp[-28].u.i; a[5] = yyvsp[-26].u.i; a[6] = yyvsp[-24].u.i; a[7] = yyvsp[-22].u.i; a[8] = yyvsp[-20].u.i; a[9] = yyvsp[-18].u.i; a[10] = yyvsp[-16].u.i; a[11] = yyvsp[-14].u.i; a[12] = yyvsp[-12].u.i; a[13] = yyvsp[-10].u.i; a[14] = yyvsp[-8].u.i; a[15] = yyvsp[-6].u.i; if (his_addr.su_family == AF_INET6) { /* XXX more sanity checks! */ data_dest.su_sin6.sin6_scope_id = his_addr.su_sin6.sin6_scope_id; } if (yyvsp[-40].u.i != 6 || yyvsp[-38].u.i != 16 || yyvsp[-4].u.i != 2) memset(&data_dest, 0, sizeof(data_dest)); #endif /* INET6 */ } break; case 75: #line 1040 "ftpcmd.y" { char *a, *p; memset(&data_dest, 0, sizeof(data_dest)); #ifndef LINUX /* BSD source */ data_dest.su_sin.sin_len = sizeof(struct sockaddr_in); #endif data_dest.su_family = AF_INET; p = (char *)&data_dest.su_port; p[0] = yyvsp[-2].u.i; p[1] = yyvsp[0].u.i; a = (char *)&data_dest.su_sin.sin_addr; a[0] = yyvsp[-12].u.i; a[1] = yyvsp[-10].u.i; a[2] = yyvsp[-8].u.i; a[3] = yyvsp[-6].u.i; if (yyvsp[-16].u.i != 4 || yyvsp[-14].u.i != 4 || yyvsp[-4].u.i != 2) memset(&data_dest, 0, sizeof(data_dest)); } break; case 76: #line 1059 "ftpcmd.y" { yyval.u.i = FORM_N; } break; case 77: #line 1063 "ftpcmd.y" { yyval.u.i = FORM_T; } break; case 78: #line 1067 "ftpcmd.y" { yyval.u.i = FORM_C; } break; case 79: #line 1074 "ftpcmd.y" { cmd_type = TYPE_A; cmd_form = FORM_N; } break; case 80: #line 1079 "ftpcmd.y" { cmd_type = TYPE_A; cmd_form = yyvsp[0].u.i; } break; case 81: #line 1084 "ftpcmd.y" { cmd_type = TYPE_E; cmd_form = FORM_N; } break; case 82: #line 1089 "ftpcmd.y" { cmd_type = TYPE_E; cmd_form = yyvsp[0].u.i; } break; case 83: #line 1094 "ftpcmd.y" { cmd_type = TYPE_I; } break; case 84: #line 1098 "ftpcmd.y" { cmd_type = TYPE_L; cmd_bytesz = CHAR_BIT; } break; case 85: #line 1103 "ftpcmd.y" { cmd_type = TYPE_L; cmd_bytesz = yyvsp[0].u.i; } break; case 86: #line 1109 "ftpcmd.y" { cmd_type = TYPE_L; cmd_bytesz = yyvsp[0].u.i; } break; case 87: #line 1117 "ftpcmd.y" { yyval.u.i = STRU_F; } break; case 88: #line 1121 "ftpcmd.y" { yyval.u.i = STRU_R; } break; case 89: #line 1125 "ftpcmd.y" { yyval.u.i = STRU_P; } break; case 90: #line 1132 "ftpcmd.y" { yyval.u.i = MODE_S; } break; case 91: #line 1136 "ftpcmd.y" { yyval.u.i = MODE_B; } break; case 92: #line 1140 "ftpcmd.y" { yyval.u.i = MODE_C; } break; case 93: #line 1147 "ftpcmd.y" { if (logged_in && yyvsp[0].s) { char *p; /* * Expand ~user manually since glob(3) * will return the unexpanded pathname * if the corresponding file/directory * doesn't exist yet. Using sole glob(3) * would break natural commands like * MKD ~user/newdir * or * RNTO ~/newfile */ if ((p = exptilde(yyvsp[0].s)) != NULL) { yyval.s = expglob(p); free(p); } else yyval.s = NULL; free(yyvsp[0].s); } else yyval.s = yyvsp[0].s; } break; case 95: #line 1178 "ftpcmd.y" { int ret, dec, multby, digit; /* * Convert a number that was read as decimal number * to what it would be if it had been read as octal. */ dec = yyvsp[0].u.i; multby = 1; ret = 0; while (dec) { digit = dec%10; if (digit > 7) { ret = -1; break; } ret += digit * multby; multby *= 8; dec /= 10; } yyval.u.i = ret; } break; case 96: #line 1205 "ftpcmd.y" { yyval.u.i = check_login1(); } break; case 97: #line 1212 "ftpcmd.y" { if (noepsv) { reply(500, "EPSV and EPRT commands disabled."); yyval.u.i = 0; } else yyval.u.i = check_login1(); } break; case 98: #line 1224 "ftpcmd.y" { if (readonly) { reply(550, "Permission denied."); yyval.u.i = 0; } else yyval.u.i = check_login1(); } break; case 99: #line 1236 "ftpcmd.y" { #ifdef USE_SSL if (logged_in || ssl_apbu_flag) yyval.u.i = 1; else { reply(534, "Please login with USER and PASS."); yyval.u.i = 0; } #else /* !USE_SSL */ /* do nothing */ yyval.u.i = 1; #endif /* USE_SSL */ } break; #line 2754 "ftpcmd.c" } yyssp -= yym; yystate = *yyssp; yyvsp -= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("%sdebug: after reduction, shifting from state 0 to\ state %d\n", YYPREFIX, YYFINAL); #endif yystate = YYFINAL; *++yyssp = YYFINAL; *++yyvsp = yyval; if (yychar < 0) { if ((yychar = yylex()) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal-symbol"; printf("%sdebug: state %d, reading %d (%s)\n", YYPREFIX, YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("%sdebug: after reduction, shifting from state %d \ to state %d\n", YYPREFIX, *yyssp, yystate); #endif if (yyssp >= yysslim && yygrowstack()) { goto yyoverflow; } *++yyssp = yystate; *++yyvsp = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: return (1); yyaccept: return (0); }