요약
- RFC 1408은 Telnet 옵션 36에
VAR=0과VALUE=1을 할당했지만, RFC 1571은 BSD 참조 구현이 두 의미를 반대로 사용했다고 문서화했다. 따라서 동일한 바이트 스트림이 서로 호환되지 않는 두 사전으로 파싱될 수 있었다. - RFC 1571은 메시지 문법, 즉 불법 마커, 순서, 개수, 익숙한 이름을 통해 상대편을 식별하려 했지만, 증거가 여전히 모호하게 남는 사례도 인정했다.
- RFC 1572는 RFC가 정의한 매핑을 유지하면서 그것을 새로운 옵션 39,
NEW-ENVIRON으로 옮겼다. 그럼에도 해석된 변수는 원격 입력일 뿐이었고, 무시할지, 대체할지, 적용할지는 서버가 결정했다.
0은 사전 없이 도착했다
RFC 1408은 1993년 1월, Telnet 연결을 통해 환경 정보를 전달하기 위해 등장했다. 그 옵션 번호는 36이었다. 서브협상 안에서IS는 0,SEND는 1,INFO는 2였다. 한 단계 아래 문법 수준에서는VAR에 0,VALUE에 1,ESC에 2,USERVAR에 3이 할당되었다.
이 작은 할당들이 수행한 일은 컸다. 수신 측은 변수 이름과 값을 구별하고, 정의되지 않은 변수와 정의되었으나 비어 있는 변수를 구별하고, 잘 알려진 이름과 사용자가 만든 이름을 구별하고, 문법적 제어 옥텟과 리터럴 제어 옥텟을 구별해야 했다. 송신자와 수신자가 0과 1에 대해 불일치하면 메시지는 단순히 잘못된 레이블을 담는 데 그치지 않고, 구조 자체가 달라졌다.
이 충돌은 1년 뒤 공개되었다.RFC 1571은 RFC 1408의VAR와VALUE정의가 BSD Telnet Environment 구현과 반대였다고 밝혔다. BSD는 우연한 대안으로 묘사되지 않았다. 그 문서는 BSD를 원래 RFC가 문서화했어야 할 참조 구현이자 수많은 기존 구현의 기반이라고 불렀다.
이 설명은 배포 규모 조사를 제공하지 않으며, 그렇게 과장해서도 안 된다. 이것은 저자들이 직면한 상호운용성 문제를 확립한다. 옵션 36은 실행 중인 소프트웨어에서는 한 가지 해석으로, 표준 트랙 텍스트에서는 다른 해석으로 존재했다. 번호만으로는 더 이상 하나의 문법을 선택하지 못했다.
옵션이 운반한 것은 Telnet 자신의 진실이 아니라 시작 컨텍스트였다
ENVIRON의 동기는 실용적이었다. 운영체제에는 사용자가 다른 호스트에 접속할 때 전파하길 원하는 시작 정보가 있었다. 새 항목마다 별도의 Telnet 옵션을 만들면 프로토콜이 특수 목적의 협상을 계속 쌓이게 될 것이었다. RFC 1408은 대신 범용 전달자를 정의했다.
문서는 6개의 잘 알려진 변수를 지정했다:USER,JOB,ACCT,PRINTER,SYSTEMTYPE,DISPLAY.USERVAR는 임의의 이름/값 쌍을 위한 공간을 마련하면서, 소프트웨어가 사용자 제공 이름과 잘 알려진 클래스를 구별할 수 있게 했다. 이 구분은 출처에 관한 것이지 인증이 아니었다. RFC 1408은 신중한 구현이 두 클래스를 똑같이 불신할 수 있다고 지적했고, 잘 알려진 이름과 사용자 이름 사이의 충돌 처리는 구현별 사항으로 남겼다.
문법은 또한 성급한 키/값 내보내기가 무너뜨릴 상태들을 보존했다. 뒤에VALUE가 없는 변수는 정의되지 않은 것이었다.VALUE바로 뒤에 다른 타입이 오거나 서브협상이 끝나면, 변수는 존재하지만 비어 있다는 뜻이었다. 빈 환경도 유효한 응답이었다. 이들은 송신자가 인코딩한 응답에 대한 정밀한 서술이지, 사람이나 계정 또는 미래의 프로세스에 대한 증명이 아니었다.
허가에는 방향이 있었다
기본 상태에서는 어떤 환경 정보도 이동하지 않았다. 초기 상태는WONT ENVIRON과DONT ENVIRON이었다. 한 끝점은WILL로 보낼 준비가 되어 있다고 말하고, 다른 끝점은DO로 받을 준비가 되어 있다고 말했다.SEND를 발행할 수 있는 것은DO측뿐이었고,IS로 응답하거나 이후 변경을INFO로 알릴 수 있는 것은WILL측뿐이었다.
이 분리가 중요했다.IS는 초기 요청-응답 경로에 속했다.INFO는 협상 후에 변경 사항을 보고하기 위해 자발적으로 생성될 수 있었지만, 초기 교환이 아니었다.WILL의 기록은SEND가 뒤따랐다는 증명이 아니었다.SEND는 특정 변수가 존재한다는 증명이 아니었다.IS프레임은 수신자가 내용을 수용했다는 증명이 아니었다.
이 교환은 흔히 연결 시작 부근에서 일어났다. 많은 운영체제가 프로세스를 생성할 때만 환경을 전파하기 때문이다. 타이밍은 가능한 효과를 바꿨다. 프로세스 생성 이후에 해석된 정보는 유효한 Telnet 메시지이면서도, 그것이 영향을 주려던 시작 메커니즘에는 너무 늦게 도착할 수 있었다.
수신자가 미래의 결정을 보유했다
RFC 1408은 전송을 명령으로 바꾸는 일을 명시적으로 거부했다. 수신 호스트는 받은 모든 변수를 사용자 환경에 넣을 의무가 없었다. 알려지지 않은 이름을 무시할 수 있었다.USER,ACCT등의 정보를 사용해 로그인 컨텍스트를 선택하면서도 그 문자열을 결과 환경에 복사하지 않을 수 있었다. 더 정확한 메커니즘으로 얻은 정보를 우선할 수도 있었다.
문서의TERM예제가 이 우선순위를 구체화했다. Telnet Terminal-Type 옵션이 이미 단말 유형을 확립한 뒤 클라이언트가USERVAR TERM=xterm을 보내면, 서버는 그 환경 변수를 무시할 수 있었다.DISPLAY에 대해서는 또 다른 규칙이 주어졌다: 환경 변수가 별도의 X-Display-Location 옵션과 충돌할 때는 가장 최근에 받은 정보가 우선해야 한다.
이들은 로컬 해결 정책이다. 공통 프로토콜은 경쟁하는 입력들을 판독 가능하게 만들었지만, 송신자를 수신자 프로세스의 주재자로 임명하지 않았다. 수신된USER는 클라이언트가 사용하려는 계정을 가리켰을 뿐, 인증이 아니었다. 수신된PRINTER는 목적지가 존재하거나 허가되었거나 실제로 인쇄했다는 증명이 아니었다. 해석된DISPLAY는 작동 중인 X 연결이나 보이는 창을 증명하지 않았다.
이 경계는 동시에 보안 경계였다. RFC 1408은 구현자에게 로그인 전에 어떤 변수가 안전한지 분석하라고 경고했다. 공격자가 통제하는 값이 로그인 또는 인증 프로그램을 변경하도록 허용하면 우회나 침해가 가능할 수 있었다. RFC는 그런 사건을 보고하지 않았다. 구조적 위험을 진술했다: 인증 전 입력과 로컬 시작 권한은 혼동되어서는 안 된다.
RFC 1571은 문법을 필드 탐지기로 만들었다
옵션 36의 두 해석이 공존하는 순간부터, 수신자는 RFC를 더 열심히 읽음으로써 과거를 수복할 수 없었다. 상대편 메시지 형태에서 증거를 얻어야 했다. RFC 1571은 휴리스틱을 제시했다.
클라이언트가SEND를 파싱할 때, 규칙은 불가능성에서 시작했다. 적합한 요청에는VAR와USERVAR가 포함되어야 하고, 절대VALUE가 포함되어서는 안 된다. 클라이언트가 자기 사전에서VALUE라고 부르는 마커를 보면, 서버가 0과 1을 뒤집었음을 추론하고 요청의 나머지와 응답에 대해 자기 해석을 뒤집을 수 있었다. 0도 1도 나타나지 않으면 증거가 없는 것이므로, 클라이언트는 공표된 정의를 가정했다.
서버의 작업은 더 어려웠다.IS와INFO는 이름과 값을 함께 운반하기 때문이다. 첫 마커가VAR이면 공표된 순서를,VALUE이면 뒤집힌 순서를 추론할 수 있었다. 메시지가USERVAR로 시작하면 어떤 파싱 하에서는 0과 1 모두 합법적으로 뒤따를 수 있었다. 서버는 그때 연속된 마커, 빈 마커, 상대적 개수, 인식 가능한 잘 알려진 이름을 찾았다.
이것은 실시간으로 수행되는 프로토콜 고고학이었다. 수신자는 상대의 정체를 발견하는 것이 아니라, 어느 역사적 사전이 바이트를 가장 잘 설명하는지 분류하고 있었다. 어떤 패턴은 한 파싱이 문법을 위반하기 때문에만 결정적이었다. 다른 패턴은 단지 개연적이었다. 모든 검사가 실패하면 RFC 1571은 서버에게 공표된 정의를 가정하라고 지시했다.
이 폴백은 기발한 검사만큼이나 중요하다. 휴리스틱 결과는 새로 관찰된 송신자에 대한 사실이 아니라 불완전한 증거 아래에서 내려진 운영상의 선택이었다. 해석된 변수만 기록하는 구현은 그 선택을 감사하는 데 필요한 역사 자체를 버린다: 옵션 번호, 원시 서브협상, 가정된 사전, 그 사전을 고른 휴리스틱, 남은 모호성.
새 번호가 새 의미를 보호했다
RFC 1572는 1994년 1월에 더 깔끔한 미래 경로를 제시했다. RFC가 정의한VAR=0,VALUE=1매핑을 유지하면서 프로토콜을 Telnet 옵션 39,NEW-ENVIRON으로 옮겼다. 문서는 새 옵션 번호를 부여하면 구현이 모호함 없이 상호운용할 수 있다고 설명했다.
이것은 0을 1로 고치거나 1을 0으로 고치는 것보다 더 미묘했다. 옵션 36은 이미 역사를 운반하고 있었다. 그 표를 다시 발행해도, 주어진 설치 구현이 문서를 따르는지 BSD를 따르는지 상대편에 알려줄 수 없었다. 옵션 39는 새로운 결정론적 공통 계층을 만들었다. 새 번호의 협상이, 그 뒤에 어떤 구형 계보가 있는지 추측할 필요 없이 새 문법을 선택했다.
현재의IANA Telnet Options 레지스트리는 두 이름을 모두 보존한다. 옵션 36은 RFC 1408과 함께 Environment Option으로 남아 있고, 옵션 39는 RFC 1572와 함께 New Environment Option이다. 레지스트리는 이 분열을 기록한다. 그러나 어떤 호스트가 두 옵션 중 하나를 구현했는지, 협상이 성공했는지, 변수가 프로세스에 도달했는지를 증명하지는 않는다.
새 번호가 로컬 판단의 필요를 지우지도 않았다. NEW-ENVIRON은 같은 방향적 동의, 요청/응답 구조, 변수 출처, 수신자 재량을 유지했다. 공통 문법은 모호하지 않게 되었지만, 운영상의 미래는 여전히 로컬에 남았다.
증거 사다리는 패킷보다 길었다
전체 사슬은 공표된 할당에서 시작한다. 구현이 어떤 사전으로 바이트를 내보낸다. 상대편이 다른 사전으로 파싱하거나 휴리스틱으로 상대를 분류한다. 디코더가 후보 이름/값 시퀀스를 만든다. 수신자는 그 출처를 기록하고 무시할지, 대체할지, 적용할지 결정한다. 로그인이나 프로세스 생성이 선택된 입력을 소비할 수 있다. 응용 프로그램이 결과 환경을 관찰할 수 있다. 외부 동작이나 사용자에게 보이는 결과를 보여주는 것은 별개의 증거뿐이다.
어떤 단계도 다음 단계의 권위를 물려받지 않는다. RFC 발행은 설치된 코드를 다시 쓰지 않았다. 파싱이 파싱을 인증하지 않았다. 인식된 변수 이름이 송신자를 인증하지 않았다. 협상된 의사가 전송을 증명하지 않았다. 전송이 적용을 강제하지 않았다. 프로세스 상태가 실행을 증명하지 않았다. 명령, 인쇄 작업, 화면 효과에는 각자의 기록이 필요했다.
출처
- RFC 1408 — Telnet Environment Option
- RFC 1408의 RFC Editor 기록
- RFC 1571 — Telnet Environment Option Interoperability Issues
- RFC 1571의 RFC Editor 기록
- RFC 1572 — Telnet Environment Option
- RFC 1572의 RFC Editor 기록
- RFC 854 — Telnet Protocol Specification
- RFC 855 — Telnet Option Specifications
- IANA Telnet Options 레지스트리
- RFC 1091 — Telnet Terminal-Type Option
- RFC 1096 — Telnet X Display Location Option
이 출처들은 지정된 문법, BSD 충돌에 대한 당시의 보고, 휴리스틱 호환 절차, 새 옵션 번호, 레지스트리 기록을 확립한다. 그러나 이름이 밝혀진 특정 구현, 배포 점유율, 악용 사례, 인증된 로그인, 수용된 환경, 생성된 프로세스, 실행된 명령, 현재의 운영 위험은 확립하지 않는다.
회원 브리핑
프로필 심층 컨텍스트
올바른 멤버십 등급으로 로그인하면 전체 브리핑과 출처 노트를 볼 수 있습니다.
Strategic Circle 전용
Strategic Circle
모든 독자에게 공개됩니다. 가입 후 로그인하면 프로필 브리핑를 열람할 수 있습니다.
Strategic Circle 가입하기Leadership Alliance 전용
Leadership Alliance
자격을 갖춘 IP 자산 소유자 및 운영진을 위한 콘텐츠입니다. 로그인하면 Leadership Alliance 브리핑을 열람할 수 있습니다.
Leadership Alliance 가입하기





