|
들어가는 글
안전한 프로그램을 작성하는 지침이 하나 이상 존재한다면, 그 중 하나는 최소 권한 이론(the principle of least privilege)일 것입니다. 최소 권한 이론은 프로그램이 수행하는 어떠한 동작도 성공적으로 완료되기 위해서는 최소한의 권한만으로 수행되어야함을 명시하고 있습니다.
(다양한 버전의 Trusted 솔라리스의 출시에도 불구하고) 솔라리스10 이전 버젼을 포함한 기존의 UNIX는 "최소" 권한이란 관점에 대해 매우 많은 헛점을 가지고 있었습니다. 이전에는 오직 두가지 레벨의 권한만을 지원해 왔습니다. 일반 유저와 흔히 슈퍼 유저 혹은 root(user ID 0으로 구분 되는 유저)라 불리는 유저. 다시 말해 솔라리스10 이전에는 권한에 대해서 "all or nothing"의 접근 방식을 취해 왔습니다. 즉, 유효 유저 ID 0으로 실행되는 프로세스는 기본적으로 아무런 제약도 없고, 다른 프로세스들은 많은 제약을 가지고 있는 것입니다.
제한적인 선택 때문에 프로그램이 사용하는 권한을 제한 할 수 있는 다른 메카니즘이 사용되어 왔습니다: set-user-ID 혹은 set-group-ID. 이것은 프로세스가 수행 될때 그 프로세스를 수행한 유저의 권한 대신 특정한 유저/ 혹은 그룹 셋의 권한으로 수행 되는 것을 의미 합니다. 우리가 어떤 특정한 파일에 데이타를 저장하는 프로그램을 가지고 있다고 할때 프로그램은 파일이 어떻게 수정되는지에 대한 제한을 가져야 합니다. 우리는 프로그램을 set-userID(SUID) root로 만들 수 있지만 좀더 안전한 방법은 프로그램을 원래 유저대로 놔두고 필요할때 해당 권한의 유저로 바뀌는 방법을 취하는 것이 될 것입니다. passwd 프로그램은 이 것의 한 예제입니다. 그러나 최고의 방법은 파일 내에 지정된 특정 userID의 유저 만이 쓰기가 가능한 것이 될 것입니다. 우리는 이 모델에 대해 더이상 토의하진 않을 것입니다. 왜냐하면 그 사용이 매우 제한되어 있기 때문입니다. 대신 이 글의 나머지 부분은 솔라리스 권한 모델을 이용하여 권한의 분리를 구현하는 방법에 대해 설명 합니다.
프로그램이 수행하길 원하는 많은 수의 권한이 필요한 작업이 있다고 해봅시다.(권한이 필요한 작업이란 어떠한 다른 프로세스에 의해서도 수행되거나 수행 되서는 안되는 작업을 의미 합니다) 우리가 이전에 인정한 대로 솔라리스의 "all or nothing" 모델은 프로그램이 권한이 필요한 작업을 수행 할때 이론적으로 모든 권한이 필요한 작업을 수행 할 수 있다는 것을 의미 합니다. 예를 들어 프로그램이 예약된 포트를 바인딩 하는 것이 필요할때 디자인 상의 문제로 시스템을 셧다운 시킬 수도 있다는 것을 의미 합니다. 이것은 권한의 분리가 잘못됨으로써 원치 않은 결과가 생길 수도 있음을 의미 합니다.
권한의 분리를 통해 우리는 권한이 실제로 요구 될때에만 해당 권한을 활성화 시키고 더이상 요구되지 않을때 비활성화 시키도록 할 수 있습니다. 가장 안좋은 상황은 모든 권한이 요구되는 요구되지 않는 무조건 활성화 되어 있을때 입니다. 이름에서 보면 알 수 있듯이 권한의 활성화외 비활성화를 통해 권한이 필요한 작업을(특히 시스템 콜등) 분리("bracket") 합니다. 다음의 가상 코드를 보시기 바랍니다:
priv_on () perform_privileged_operation () priv_off () |
권한 분리의 아이디어는 프로그램의 취약성을 최대한 줄임으로써 어떠한 시스템이 해킹 당했을때의 데미지를 최소한으로 줄여 줍니다. 예를 들어 프로세스가 파일을 써야 한다면 파일은 오직 쓰기 권한만을 이용해 열리면 됩니다. 다시 말해 우리는 오직 open 시스템 콜에만 권한을 부여 합니다 (사용 후에 바로 권한을 포기함); 우리는 write 시스템 콜에 권한을 부여할 필요가 없습니다
어떠한 예외도 없이 권한이 필요한 작업을 수행하는 모든 프로그램들은 권한 분리를 사용해야 합니다. 이것은 그들이 이산적인 프로세스 권한을 사용 하더라도 역시 마찬 가지 입니다. (솔라리스10 에 앞서 권한 분리는 seteuid 함수를 이용해 이루어 졌습니다. 비록 그것은 완벽하진 않았지만 적어도 그것을 전혀 사용하지 않는 것보단 낳았습니다).
솔라리스10은 프로세스 권한이라는 기능을 새로 제공해서 유효 UID가 0인 프로세스가 모든 권한을 가지고 있었던 상황을 분산된 여러가지의 권한으로 나누었습니다. 이전의 예를 다시 설명하자면 이제 프로세스가 특정한 포트를 바인드해야 한다면 적절한 권한을 지정함으로써 이러한 기능만을 수행 하도록 할 수 있습니다 (PRIV_NET_PRIVADDR); 프로그램이 적절하게 작성되었다면 이제 다른 권한이 필요한 작업 (시스템의 파일을 읽거나 쓰는 일 같은) 은 더 이상 가능하지 않습니다. privileges 맨 페이지는 사용 가능한 권한들에 대해 설명해 줍니다. (참고로 만약 우리가 어떠한 권한이 없이 어떠한 작업을 이미 수행할 수있다면 권한 체크는 일반적으로 이루어지지 않습니다.)
권한에 대한 솔라리스의 구현은 4가지 셋을 사용 합니다:허용 셋 (P), 상속 셋 (I), 제한 셋 (L), 유효 셋 (E).
P 는 프로세스가 잠재적으로 사용 할 수 있는 권한의 셋을 정의 합니다. P 에 존재하지 않는 권한은 프로그램에 지정될 수 없습니다. P는 프로세스가 부모 프로세스에게 상송을 받아서 생성될때 초기화 됩니다. 프로세스는 P에서 권한을 제거 할 수 있지만 추가할 수는 없습니다. P에서 제거된 권한들은 자동적으로 E에서도 지워 집니다.
I 는 exec 를 호출 한 후에 자식 프로세스들 에게 전달되어 지는 권한의 셋을 정의 합니다. I 와 P는 보통 같지만 I에서 제거된 권한이 P에는 존재하는게 이상한 일은 아닙니다.
L 은 자식 프로세스에게 넘기거나 지정하는 권한 셋들의 상위 제한을 정의 합니다. 다른 권한 셋들관 다르게 L을 변경하더라도 이 다음 exec 가 수행될때 까지는 유효하지 않습니다. L 은 전형적으로 권한의 모든 셋(혹은 모든 존의 권한)과 같습니다.
E 는 현재 사용 중인 권한의 셋을 정의 합니다. 프로세스가 시작되면 E와 P는 같습니다 결과적으로 E는 P의 서브셋 이거나 동일합니다.
각 프로세스는 관련된 플래그들을 가지고 있고 이를 통해 각 프로세스의 상태를 알 수 있습니다;프로세스가 권한에 대해 인지하고 있는지 혹은 인지하지 못하고 있는지. 기본적으로 프로세스는 권한에 대해 인지 하지 못하고 있습니다;다음의 두가지 작업을 수행 함으로써 권한을 인지 하게 됩니다:
- P, L 혹은 E를
setppriv를 호출 하여 조작 setpflags을 사용
두가지 프로세스 타입에서 권한이 어떻게 처리 되는지 알아 보기 위해 두가지 타입의 E 와 P 권한 셋을 소개 하겠습니다.: 관찰되는 셋은 셋 이름 앞에 "o"를 붙이고 구현 셋에는 "i"를 붙이도록 하겠습니다.
프로세스가 권한을 인지했을때 다음의 대입이 일어 납니다:
iE = oE
iP = oP
oE 와 oP 셋들은 권한을 인지하고 있는 프로세스가 UID를 변경하더라도 변하지 않습니다. 반대로 프로세스가 권한을 인지 하고 있지 못하다면 oE와 oP는 다음과 같이 지정 됩니다:
oE = (euid == 0) ? L : iE
oP = (euid == 0 || ruid == 0 || suid == 0) ? L : iP
다시 말해 만약 euid 가 0과 같다면 oE 는 L로 셋팅 되고 그렇지 않다면 그것은 iE로 셋팅 됩니다(L의 서브셋). 비슷하게 만약 euid, ruid 혹은 suid가 0과 같다면 oP는 L로 셋팅 되고 그렇지 않다면 iP로 셋팅 됩니다. 이 것의 부작용으로는 권한을 인식하지 못하는 SUID 루트 프로세스가 권한을 포기 할때 모든 권한을 가지고 있지 않는 일이 발생할 수 있습니다.(이것은 로컬존의 UID 0의 프로세스라도 다른 존의 프로세스에는 영향을 줄수 없다는 속성 때문입니다.)
우리는 이것을 ppriv 커맨드를 이용해서 데모해 볼 수 있습니다. 즉 이것을 이용해서 프로세스의 권한 셋을 수정하거나 출력하고 프로그램을 특정한 권한 셋을 지정하여 실행 할 수도 있습니다. 일단 ppriv 의 일반적인 사용 방법을 보시겠습니다:
rich@excalibur4167# id
uid=1001(rich) gid=10(staff)
rich@excalibur4168# ppriv $$
803: /bin/ksh
flags = <none>
E: basic
I: basic
P: basic
L: all
|
이제 우리는 root 로 접속 할 것이고 ppriv 다시 실행할 것입니다:
rich@excalibur4169# su -
Password:
Sun Microsystems Inc. SunOS 5.11 snv_23 October 2007
root@excalibur503# ppriv $$
4795: /usr/bin/ksh
flags = <none>
E: all
I: basic
P: all
L: all
|
우리가 기대했던 대로 root 쉘은 모든 사용 가능한 권한을 가지고 있습니다. 이것은 다른 유저의 패스워드를 치지 않고도 다른 유저로 로그인 할 수 있음을 의미 합니다:
root@excalibur511# su - rich
Sun Microsystems Inc. SunOS 5.11 snv_23 October 2007
rich@excalibur4096# ppriv $$
4808: -ksh
flags = <none>
E: basic
I: basic
P: basic
L: all
|
다시 한번 말해 우리가 기대했떤대로 일반적인 유저는 기본 권한 셋 이외에 어떠한 권한도 가지고 있지 않습니다. 일반 유저의 쉘을 빠져 나온 다음 root 권한이 다시 되면 권한이 축소된 L를 사용해 다른 유저의 쉘로 접근해 봅시다:
root@excalibur512# ppriv $$
4795: /usr/bin/ksh
flags = <none>
E: all
I: basic
P: all
L: all
root@excalibur513# ppriv -e -s L=basic ksh
root@excalibur514# ppriv $$
4821: ksh
flags = <none>
E: basic
I: basic
P: basic
L: basic
root@excalibur515# su - rich
Could not join default project
su: unable to set credentials
|
이번에는 유저 ID 0으로 시작함에도 불구하고 유저 아이디를 변경할 수 없습니다. 왜냐하면 권한을 축소 시켰기 때문입니다. 좀 더 검사하기 위해 그리고 왜 기본 프로젝트 혹은 셋 크레덴셜을 조인 할 수 없는지 알아보기 위해 우리는 ppriv에 -D 를 커맨드라인 옵션으로 주어서 디버그 모드로 실행 시킵니다.:
root@excalibur519# ppriv -D -e -s L=basic ksh root@excalibur520# su - rich su[917]: missing privilege "proc_audit" (euid = 0, syscall = 186) needed at auditsys+0x81 su[917]: missing privilege "proc_taskid" (euid = 0, syscall = 70) needed at tasksys_settaskid+0x49 Could not join default project su: unable to set credentials |
여기 우리는 su 커맨드가 실패 했음을 알 수 있습니다. 왜냐하면 우리는 proc_audit 과 proc_taskid 권한을 지정하지 못했기 때문입니다.(왜냐하면 우리는 제한 권한 셋을 기본 권한 셋으로 제한 시켰기 때문입니다).
이제 우리는 권한에 대한 몇가지 배경 지식을 가지고 있고 몇가지 사용 예제도 보았습니다. 이제 권한을 인지하는 프로그램에서 사용하기 위한 함수와 데이타 형에 대해 알아보겠습니다. 이 것들은 <priv.h> 헤더 파일에 지정되어 있습니다.
개인 권한은 priv_t 라고 불리는 데이타 형에 의해 나타내어 지고 이것은 권한 ID 문자열에 의해 초기화 될 수 있습니다. 예를 들어:
priv_t priv = PRIV_FILE_DAC_READ; |
비슷하게 권한의 셋은 priv_set_t 이라고 불리는 불투명한 데이타 타입으로 나타내어 집니다. 우리는 이 값을 priv_str_to_set 을 사용해서 변경하거나 관계된 함수를 통해 변경 할 수 있습니다. 주의할 점은 비록 커널에서 숫자들이 권한들을 나타내기 위해 사용되더라도 주어진 권한의 이름에 대한 숫자의 매핑은 현재 커널 에서만 유효하고 다음번 부팅 시에 바뀔 수도 있습니다. 이러한 이유로 인해 우리는 권한을 숫자를 이용해서 지정하면 안되고 반드시 ID 문자열을 사용해야 합니다.
이제 몇몇 프로세스 권한 함수에 대해 알아 보겠습니다. 어떻게 활요하는 지에 대한 예제는 이글의 후에 나오게 됩니다.
setppriv 함수setppriv 함수는 이전에 언급했던 어떠한 4가지 셋에 대해서도 추가, 제거, 교체 등의 작업을 하는데에 사용 됩니다. 이것은 다음과 같은 프로토타입을 가지고 있습니다:
int setppriv (priv_op_t op, priv_ptype_t which, const priv_set_t *set); |
op 매개변수는 어떠한 작업을 수행할지 지정하고 다음의 값중 하나가 될 수 있습니다:
PRIV_ON 이것은 set 에 의해 지정되는 권한을 which 에 의해 지정된 권한 셋에 추가 시키는 작업을 수행 합니다.
PRIV_OFF 이것은 set 에 의해 지정되는 권한을 which 에 의해 지정된 권한 셋에서 제거 시키는 작업을 수행 합니다.
PRIV_SET 이것은which 에 의해 지정되는 권한 셋을 set 에 의해 지정되는 셋으로 교체 시키는 작업을 수행 합니다.
which 매개변수는 어떠한 권한 셋이 변경되어야 하는지 지정합니다. 그리고 반드시 다음 중에 하나가 되어야 합니다: PRIV_PERMITTED, PRIV_INHERITABLE, PRIV_LIMIT, 혹은 PRIV_EFFECTIVE.
priv_set 함수priv_set 함수는 setppriv 의 간편한 래퍼이고 다음과 같은 프로토 타입을 가지고 있습니다:
int priv_set (priv_op_t op, priv_ptype_t which, ...); |
op 와 which 매개변수는 setppriv 에서와 동일한 의미를 가지고 있고 which 의 추가 값 PRIV_ALLSETS 은 작업이 모든 권한 셋에 모두 적용 되도록 한다는 것을 의미 합니다. 3번째 그리고 그후의 매개 변수는 NULL 로 종료되는 권한 이름들의 목록이 됩니다.
priv_str_to_set 함수priv_str_to_set 함수는 하나 혹은 그 이상의 권한 이름을 포함하는 문자열을 권한 셋으로 변환 시키는데 사용됩니다. 다음과 같은 프로토타입을 가지고 있습니다:
priv_set_t *priv_str_to_set (const char *buf, const char *sep, const char **endptr); |
첫번째 매개변수 buf 는 sep 에 의해 가르켜지는 문자열 내에서 문자들로 분리 되어 지는 하나 혹은 그 이상의 권한 이름으로 이루어 져 있는 권한 명세를 가르키고 있습니다. 만약endptr 가 NULL 이 아니라면 그리고 만약 문자열을 파싱하는데 에러가 발생한다면 나머지 문자열의 포인터가 그 안에 저장 됩니다. 성공적으로 작업이 완료 되면 priv_set_t 자료 구조의 포인터가 리턴 됩니다. 어플리케이션은 반드시 이 구조체가 더 이상 필요하지 않을 때 priv_freeset 를 명시적으로 호출해서 메모리 반환 해야 합니다.
권한 명세는 하나 혹은 두가지 이상의 다음 문자열을 포함 할 수 있습니다: "none" 은 빈 셋, "all" 은 모든 권한, "zone" 은 존에서 사용 가능한 권한, 그리고 전통적으로 root를 제외한 유저가 접속했을때 사용 할 수 있는 권한의 셋인 "basic".
몇가지 관련된 다른 함수가 존재 하지만 여기서 설명하지는 않겠습니다.(예를 들어 priv_getbyname, priv_getbynum, priv_getsetbyname, 그리고 priv_getsetbynum). 관심있는 독자는 맨 페이지를 참고 바랍니다.
priv_addset 함수이 함수는 권한 셋에 권한을 추가 시키고 다음과 같은 프로토 타입을 갖습니다:
int priv_addset (priv_set_t *sp, const char *priv); |
priv 에 의해 명명된 권한은 sp가 가르키는 셋에 추가 됩니다. 반대로 priv_delset 함수는 권한 셋에서 권한을 제거 하는데 사용 됩니다.
priv_inverse 함수priv_inverse 함수는 권한 셋을 반전 시키는데 사용 됩니다.
void priv_inverse (priv_set_t *sp); |
sp 가 가르키고 있는 권한 셋이 반전 되서 sp 에 다시 저장됩니다.
priv_freeset 함수권한 셋의 사용이 끝나면 반드시 priv_freeset 을 이용해서 메모리 할당을 반납해야 합니다.
void priv_freeset (priv_set_t *sp); |
sp 가 가르키는 권한 셋의 저장공간이 반납됩니다.
이러한 이론들은 훌륭합니다. 그러나 이러한 함수들을 어떻게 실생활에서 사용할까요? 우리가 일반적으로는 쓸수 없는 파일 혹은 파일들을 쓸 수 있도록 요구 되는 어플리케이션을 작성한다고 가정해 봅시다. 맨 페이지를 간략히 읽어 본 결과 우리가 필요한 권한은 바로 PRIV_FILE_DAC_READ 임을 알았습니다. (DAC 는 Discretionary Access Control 의 약자로 일반적인 UNIX의 권한과 ACL을 의미 합니다).
우리는 3가지의 함수를 작성할 것입니다: priv_init, priv_on, 그리고 priv_off. 첫번째 함수는 초기화 작업을 담당하는 함수 그리고 나머지 함수들은 권한 분리를 구현한 함수들 입니다.
priv_init 함수priv_init 함수는 우리가 말하고 있는 예에서 권한의 상태를 초기화 하는 함수 입니다. 이 함수는 반드시 main 의 시작 근처에서 호출 되어서 불필요한 권한들은 모두 사용하지 않도록 해야 합니다. 진입 단계에서 모든 권한 셋은 사용 가능한 모든 권한 셋이라고 가정해서 프로그램이 set-user-ID가 root인 상태로 호출 되는 것의 부작용을 나타 내도록 합니다. 빠져나올때 권한 셋은 기본 셋에 + PRIV_FILE_DAC_READ - PRIV_PROC_FORK - PRIV_PROC_EXEC 인 상태로 합니다. 왜냐하면 priv_init 가 리턴 될때 기본 셋에 추가적인 권한들이 지정 되기 때문이고, 어플리케이션은 priv_init 을 호출 한후에 반드시 priv_off 를 바로 불러서 이것들을 비활성화 시켜야 합니다.
priv_init를 호출 하는 것은 프로세스가 권한을 인지 하도록 만드는 것의 부작용을 가지고 있습니다. (왜냐하면 because priv_init 는 내부적으로 setppriv 을 호출 하기 때문임; 사실 프로세스가 권한을 인지하도록 만드는 것은 이후에 하는 일임).
다음의 소스는 priv_init의 소스입니다. 간결성을 위해서 헤더 파일 같은 것들은 생략했습니다.
1 void priv_init (void)
2 {
3 priv_set_t *priv_set;
4 if ((priv_set = priv_str_to_set ("basic", ",", NULL)) == NULL) {
5 perror (gettext ("lock: priv_str_to_set failed"));
6 exit (1);
7 }
8 if (priv_addset (priv_set, PRIV_FILE_DAC_READ) == -1) {
9 perror (gettext ("lock: Can't add FILE_DAC_READ privilege"));
10 exit (1);
11 }
12 if (priv_delset (priv_set, PRIV_PROC_EXEC) == -1) {
13 perror (gettext ("lock: Can't remove PROC_EXEC privilege"));
14 exit (1);
15 }
16 if (priv_delset (priv_set, PRIV_PROC_FORK) == -1) {
17 perror (gettext ("lock: Can't remove PROC_FORK privilege"));
18 exit (1);
19 }
20 priv_inverse (priv_set);
21 if (setppriv (PRIV_OFF, PRIV_PERMITTED, priv_set) == -1) {
22 perror (gettext ("lock: Can't set Permitted privilege set"));
23 exit (1);
24 }
25 if (setppriv (PRIV_OFF, PRIV_LIMIT, priv_set) == -1) {
26 perror (gettext ("lock: Can't set Limit privilege set"));
27 exit (1);
28 }
29 priv_freeset (priv_set);
30 setreuid (getuid (), getuid ());
31 }
|
priv_init 을 좀 더 자세히 살펴 봅시다.
1-19 기본 권한들로 구성된 임시 권한 셋을 생성합니다. 그 다음 FILE_DAC_READ 을 추가 하고 PROC_EXEC 와 PROC_FORK 을 제거 합니다. 기본 셋에는 어플리케이션이 필요로 하지 않는 권한들이 있습니다. 그러므로 우리는 (아마 반드시) 이론적으로 그것들을 제거해주어야 합니다. 그러나 여기서는 간결성을 위해 생략하였습니다.
20-28 임시 권한 셋을 반전 시켜서 필요로 하지 않는 권한들을 얻고 난 후에 제한, 허가 셋들에서 이 것들을 제거 시킵니다.(후에 암시적으로 유효 셋에서도 제거 시킴).
29 사용이 끝난 임시 권한 셋을 할당해제 합니다. 몇몇 경우 권한 셋을 할당해제 하지 않는 것이 좋은 생각이 될 수도 있습니다: 우리는 이후의 프로그램에서 이것을 수정하길 원할 수도 있기 때문이며 이 경우 우리는 반드시 priv_freeset 을 여기서 호출 하면 안됩니다.
30 권한을 인지하고 있는 프로세스는 SUID 구문을 사용하지 않습니다. 그러므로 유효 user ID를 실제의 ID로 영구적으로 리셋 합니다. 왜냐하면 우리의 프로그램의 SUID 는 root이므로 처음 시작할때 부터 모든 필요한 권한을 가진 상태로 시작 되기 때문입니다.(우리는 오직 허가 셋에서만 권한을 제거 할 수 있음을 기억 하기 바랍니다).
priv_on 함수우리는 FILE_DAC_READ 권한을 활성화 시킬 때 priv_on 함수를 호출 합니다. 다음의 소스가 이 함수를 나타 냅니다.
1 void priv_on (void)
2 {
3 if (priv_set (PRIV_ON, PRIV_EFFECTIVE, PRIV_FILE_DAC_READ, NULL) == -1) {
4 perror (gettext ("lock: Can't enable FILE_DAC_READ privilege"));
5 exit (1);
6 }
7 }
|
위의 일곱개의 라인이 어떻게 동작하는지 봅시다.
1-7 FILE_DAC_READ 권한을 유효 권한 셋에 추가 시킴.
priv_off 함수이 함수는 priv_on의 반대 함수입니다; 그것의 코드는 다음에 담겨 있습니다.
1 void priv_off (void)
2 {
3 if (priv_set (PRIV_OFF, PRIV_EFFECTIVE, PRIV_FILE_DAC_READ, NULL) == -1) {
4 perror (gettext ("lock: Can't disable FILE_DAC_READ privilege"));
5 exit (1);
6 }
7 }
|
1-7 FILE_DAC_READ 권한을 유효 권한 셋에서 제거 합니다.
priv_on 과 priv_off를 이용한 권한 분리다음의 예제는 라이브러리 호출 근처에서 어떻게 권한을 분리하여 사용 하는지에 대한 소스 입니다. (이경우 getspnam 은 사용자 이름으로 shadow 파일에서의 엔트리를 찾는데 사용 됩니다) 이것은 lock 프로그램의 compare_passwd 함수에서 가져 왔습니다.
1 priv_on ();
2 if ((shadow_ent = getspnam (user)) == NULL) {
3 saved_errno = errno;
4 priv_off ();
5 msg = gettext ("lock: Can't get shadow database entry for %s: %s");
6 fprintf (stderr, msg, user, strerror (saved_errno));
7 exit (1);
8 }
9 priv_off ();
|
1 FILE_DAC_READ 권한을 priv_on 을 호출 하여 활성화 시킵니다. shadow 파일은 보통 root에 의해서만 읽혀지는 파일이기 ?문에 반드이 이 작업을 해야 합니다.
2-4 If an error occurred while calling getspnam 을 호출하는 중에 에러가 발생 한다면 errno 를 저장 하고 priv_off 를 사용해서 모든 권한을 비활성화 시킵니다. priv_off 에 에러가 발생할 것을 대비해서 errno 를 저장 합니다.
9 getspnam 의 호출이 성공적으로 이루어 졌따면 priv_off 를 이용하여 모든 권한을 비활성화 시킵니다.
비록 이러한 예제들이 권한 API를 이해 하는데 도움을 줬다고 하더라도 이것을 실제로 이용하기 위해서는 전체 어플리케이션을 뜯어보고 어떻게 실제로 사용하는지 이해해야 할 필요가 있습니다. 공간의 제약상 이 글에서는 그렇게 하지 못했지만 관심이 있는 독자들은 필자의 lock 프로그램을 통해 좀 더 알아 보실 수 있습니다. BSD 의 이름을 받아서 lock 은 CDDL 라이센스 된 오픈 소스 유틸리티 입니다. 다음의 링크에서 찾으 실 수 있습니다. http://www.rite-group.com/rich/sw/lock.html.
이 글은 솔라리스 권한에 대해 알아보았고 그 존재의 이유와 기존 UNIX의 모델인 "all or nothing"과의 비교도 간단히 해 보았습니다. 또한 권한 분리에 대해서도 알아 봤습니다.
우리는 권한에 대한 솔라리스 구현에 대해 설명 했고 몇가지 솔라리스 권한 API를 구성하는 함수들에 대해서도 알아 봤습니다. 마지막으로 몇가지 예제를 통해 이러한 API의 사용 방법을 알아 봤습니다: priv_init 는 프로세스의 권한을 초기화 할때 사용 하고 priv_on 와 priv_off, 는 프로그램에서 동작들의 권한을 분리 하는데 사용 하였습니다.
저자의 책인Solaris Systems Programming 은 솔라리스 어플리케이션을 개발 하는 사람에게는 기초적인 책입니다. OpenSolaris community blogs (특별히 Casper Dik 의 블로그)에서 많은 자료를 찾으 실 수 있습니다. 다른 유용한 자료는 Solaris Security for Developers Guide ( docs.sun.com) 과 두개의 썬 BluePrints 문서인: Privilege Debugging in the Solaris 10 Operating System and Limiting Service Privileges in the Solaris 10 Operating System 입니다.
여기 이러한 자료들에 대한 정보가 있습니다:
- Solaris Security for Developers Guide, Sun Microsystems, 2005, ISBN 0-595-28558-9
- Limiting Service Privileges in the Solaris 10 Operating System (pdf), Sun Microsystems, 2005
- Privilege Debugging in the Solaris 10 Operating System (pdf), Sun Microsystems, 2006
- Solaris Systems Programming, Rich Teer, 2005, ISBN 0-201-75039-2
"개발자코너" 카테고리의 다른 글
- DTrace를 사용하여 유저가 조정하는 애플리케이션 크래쉬 데이타 정보 모으기 (댓글 1개 / 트랙백 0개) 2006/08/23
- D 스크립트 배우기 (댓글 0개 / 트랙백 0개) 2009/11/23
- C++ 표준 라이브러리인 libCstd와 libstlport 비교하기 (댓글 1개 / 트랙백 0개) 2006/07/23
- 썬 스튜디오: VIS 명령을 사용하여 중요한 루틴의 속도를 향상시키기 (댓글 1개 / 트랙백 0개) 2006/02/23
- 썬 스튜디오 dbx 를 이용한 AMD64 명령어 레벨의 디버깅 (댓글 0개 / 트랙백 0개) 2007/12/14
- 솔라리스에서의 유저 인증: Part 1 (댓글 0개 / 트랙백 0개) 2007/10/21
- C++ ABI의 안정성: 프로그래밍 언어의 진화 (댓글 1개 / 트랙백 0개) 2006/02/23
- 솔라리스 디바이스 드라이버 작성을 원하십니까? (댓글 1개 / 트랙백 0개) 2008/09/18
- DLight 소개 (댓글 0개 / 트랙백 0개) 2009/06/29
- Dmalloc 을 솔라리스, 썬 스튜디오 컴파일러와 사용하기 (댓글 6개 / 트랙백 0개) 2007/06/13
댓글을 달아 주세요
좋은 정보 감사해요~
2007/09/19 04:16