[질문]c로 FTP client를 구현하는데.. user id전송후 패스워드 전송시 530 코드만..

sunnymichy의 이미지

안녕하세요.
네트워크 프로그래밍을 공부하고 있는 사람입니다..^^;
다른게 아니고.. 제가 c 언어로 ftp client를 구현하고 있는 중입니다. 그런데.. 자꾸 이상하게 동작을 해서 이렇게 조언을 구하고자 질문을 올립니다. 제가 첨부하는 소스를 보시고 혹시 틀린 부분이 있는지 조언을 부탁드립니다.

소스코드는 아래와 같습니다. 소스가 긴 관계로 현재 제가 틀린곳이 있는지 유무를 알고자하는 login()함수 부분만 적습니다.

int login()
{
	struct termio tty;
	struct sockaddr_in server_addr;

	unsigned short saveflags;
	char user_id[20];
	char passwd[20];
	char *login_name;
	int receive_code = 0;
	
	cmd_response();  // 220 response code를 받기 위함.

	login_name = malloc(BUFSIZ);  
	memset(user_id, '\0', 20);
	memset(sendbuf, '\0', sizeof(sendbuf));

	if( (login_name = getenv("LOGNAME")) == NULL)
	{
		fprintf(stderr,"can't get LOGNAME.");
	}
	fprintf(stdout,"User ID[%s:%s] : ", server_ip, login_name);
	fgets(user_id, sizeof(user_id), stdin);

	if( !strcmp(user_id,"\n") ) 		// if input '\n', user_id is current user ID.
	{	
		sprintf(sendbuf,"USER %s\r\n", login_name);
		write(control_fd, sendbuf, sizeof(sendbuf)); 	// user id를 전송. USER user_id.
	}
	else 
	{
		user_id[strlen(user_id)-1] = '\0';
		sprintf(sendbuf,"USER %s\r\n", user_id);
		write(control_fd, sendbuf, sizeof(sendbuf)); 	// user id를 전송. USER user_id.		
	}
	
	bzero(sendbuf, sizeof(sendbuf));
	if( ( receive_code = cmd_response()) == USER_OK ) 	// if login is success.
	{
		ioctl(fileno(stdout), TCGETA, &tty);	// get current tty.
		saveflags = tty.c_lflag;		// save current tty.c_lflag.
		tty.c_lflag &= ~ECHO;    		// terminal echo disable.
		ioctl(fileno(stdout), TCSETAF, &tty);	// establish tty

		printf("Password: ");
		fgets(passwd, sizeof(passwd), stdin);
		passwd[strlen(passwd)-1] = '\0';
		bzero(sendbuf,sizeof(sendbuf));
		sprintf(sendbuf,"PASS %s\r\n", passwd);
		fprintf(stdout, "\n");
		
		write(control_fd, sendbuf, sizeof(sendbuf));  // password 전송. PASS password.

		tty.c_lflag = saveflags;  		// recovery old tty.c_lflag, terminal echo enable.
		ioctl(fileno(stdout), TCSETAF, &tty);
		fprintf(stdout, "\n");

		if( (receive_code = cmd_response()) == FAILURE )
		{
			fprintf(stderr,"Logined failed.\n");
			return FAILURE_LOGIN;
		}		
		return SUCCESS_LOGIN;
	}
	else
	{
		fprintf(stdout, "User ID incorect.\n");
		return FAILURE_LOGIN;  // if login is failed. return FAILURE_LOGIN.
	}
} // end of login()

실행 결과는 아래와 같습니다.

220 (vsFTPd 2.0.1)
user ID[(null):black422] : 
DEBUG_CODE: [Line: 206, Func: login()] 
DEBUG_CODE: sendbuf = _USER black422
_ and control_fd = _3_ of id in login().
DEBUG_CODE: sendbuf[0] = 55
DEBUG_CODE: sendbuf[1] = 53
DEBUG_CODE: sendbuf[2] = 45
DEBUG_CODE: sendbuf[3] = 52
DEBUG_CODE: sendbuf[4] = 20
DEBUG_CODE: sendbuf[5] = 62
DEBUG_CODE: sendbuf[6] = 6c
DEBUG_CODE: sendbuf[7] = 61
DEBUG_CODE: sendbuf[8] = 63
DEBUG_CODE: sendbuf[9] = 6b
DEBUG_CODE: sendbuf[10] = 34
DEBUG_CODE: sendbuf[11] = 32
DEBUG_CODE: sendbuf[12] = 32
DEBUG_CODE: sendbuf[13] = d
DEBUG_CODE: sendbuf[14] = a
DEBUG_CODE: [Line: 215, Func: login()] 
DEBUG_CODE: recv_buf =_331 Please specify the password.
_ in cmd_response() 
DEBUG_CODE: response_cmd_code = _331_
 331 Please specify the password.
Password: 

DEBUG_CODE: [Line: 570, Func: cmd_response()] 
DEBUG_CODE: recv_buf =_530 Please login with USER and PASS.
_ in cmd_response() 
DEBUG_CODE: response_cmd_code = _530_
 530 Please login with USER and PASS.

Logined failed.

물론 디버그코드로 헥사값으로 출력을 해보아도 제대로 버퍼에 입력이 되어집니다.
쌀밥의 이미지

530 이면 암호가 틀린 경우인거 같은데요..

\r\n 말고 그냥 \r 만 하거나 \n만 하면 되지 않을까요? (암호 입력시와 ID입력시 모두에..)

그리고 sendbuf의 사이즈는 몇인가??

일하는 사람들의 희망 민주노동당 : http://www.kdlp.org
반공 교육의 성과로, 민주주의의 반대가 공산주의(또는 사회주의)라고 생각하는 사람이 많다.

mach의 이미지

* write(fd, buf, size)는 항상 size만큼 write하는 것은 아닙니다.
정확히는, x<= size 인 x만큼을 write하게됩니다. 리턴값 검사하라는 얘기입니다.
심지어 x <= 0 인 경우에 대해서도 검사해야 합니다. 때에 따라 중단 또는 루프돌면서 전송하는 루틴이 필요합니다.

* write(fd, buf, sizeof(buf)) 스타일에서
sizeof()를 사용하는 것은 때에따라, 실제보내야 할 크기보다 더 큰 데이터를 보낼 수 있습니다. 이를 문자열의 길이로 대체하여야 할것입니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

sunnymichy의 이미지

지적해 주신대로 sizeof() 문제 였습니다.
다시 한번 감사드립니다..

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.