全てのユーザにはuidという個別の数値が割り当てられる
$ id root
uid=0(root) gid=0(root) groups=0(root)
$ id vagrant
uid=1000(vagrant) gid=1000(vagrant) groups=1000(vagrant),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd)
hacking.h
void fatal(char *message) { char error_message[100]; strcpy(error_message, "[!!]致命的なエラー:"); strncat(error_message, message, 83); perror(error_message); exit(-1); } void *ec_malloc(unsigned int size) { void *ptr; ptr = malloc(size); if(ptr == NULL) fatal("ec_malloc()内でメモリ割り当てに失敗しました。"); return ptr; }
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include "hacking.h" void usage(char *prog_name, char *filename){ printf("使用方法: %s <%sに追加するデータ>\n", prog_name, filename); exit(0); } void fatal(char *); void *ec_malloc(unsigned int); int main(int argc, char *argv[]) { int userid, fd; char *buffer, *datafile; buffer = (char *) ec_malloc(100); datafile = (char *) ec_malloc(20); strcpy(datafile, "./notes"); if(argc < 2) usage(argv[0], datafile); strcpy(buffer, argv[1]); printf("[DEBUG] buffer @ %p: \'%s\'\n", buffer, buffer); printf("[DEBUG] datafile @ %p: \'%s\'\n", datafile, datafile); fd = open(datafile, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); if(fd == -1) fatal("main()内、ファイルのオープン中にエラーが発生しました。"); printf("[DEBUG] ファイル記述子]:%d\n", fd); userid = getuid(); if(write(fd, &userid, 4) == -1) fatal("main()内、ファイルへのユーザIDの書き込みでエラーが発生しました。"); write(fd, "\n", 1); if(write(fd, buffer, strlen(buffer)) == -1) fatal("main()内、ファイルへのバッファの書き込みでエラーが発生しました。"); write(fd, "\n", 1); if(close(fd) == -1) fatal("main()内、ファイルのクローズ中にエラーが発生しました。"); printf("メモが保存されました。\n"); free(buffer); free(datafile); return 0; }
$ gcc -o main main.c
$ ls -l ./main
-rwxrwxr-x 1 vagrant vagrant 13664 Feb 12 02:26 ./main
$ sudo chown root:root ./main
$ sudo chmod u+s ./main
$ ls -l ./main
-rwsrwxr-x 1 root root 13664 Feb 12 02:26 ./main
$ ./main “this is a test of multiuser notes”
[DEBUG] buffer @ 0xaaaaf83ba2a0: ‘this is a test of multiuser notes’
[DEBUG] datafile @ 0xaaaaf83ba310: ‘./notes’
[DEBUG] ファイル記述子]:3
メモが保存されました。
$ ls -l ./notes
-rw——- 1 root vagrant 39 Feb 12 02:31 ./notes
$ sudo cat ./notes
�
this is a test of multiuser notes
$ sudo hexdump -C ./notes
00000000 e8 03 00 00 0a 74 68 69 73 20 69 73 20 61 20 74 |…..this is a t|
00000010 65 73 74 20 6f 66 20 6d 75 6c 74 69 75 73 65 72 |est of multiuser|
00000020 20 6e 6f 74 65 73 0a | notes.|
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include "hacking.h" #define FILENAME "./notes" int print_notes(int, int, char *); int find_user_note(int, int); int search_note(char *, char *); void fatal(char *); int main(int argc, char *argv[]) { int userid, printing=1, fd; char searchstring[100]; if(argc > 1) strcpy(searchstring, argv[1]); else searchstring[0] = 0; userid = getuid(); fd = open(FILENAME, O_RDONLY); if(fd == -1) fatal("main()内、ファイルの読み込みオープンでエラーが発生しました。"); while(printing) printing = print_notes(fd, userid, searchstring); printf("-----[ メモの終わり ]------\n"); close(fd); return 0; } int print_notes(int fd, int uid, char *searchstring) { int note_length; char byte=0, note_buffer[100]; note_length = find_user_note(fd, uid); if(note_length == -1) return 0; read(fd, note_buffer, note_length); note_buffer[note_length] = 0; if(search_note(note_buffer, searchstring)) printf(note_buffer); return 1; } int find_user_note(int fd, int user_uid) { int note_uid = -1; unsigned char byte; int length; while(note_uid != user_uid){ if(read(fd, ¬e_uid, 4) != 4) return -1; if(read(fd, &byte, 1) != 1) return -1; byte = length = 0; while(byte != '\n'){ if(read(fd, &byte, 1) != 1) return -1; length++; } } lseek(fd, length * -1L, SEEK_CUR); printf("[DEBUG] uid %dの%dバイトのメモを見つけました\n", note_uid, length); return length; } int search_note(char *note, char *keyword){ int i, keyword_length, match=0; keyword_length = strlen(keyword); if(keyword_length == 0) return 1; for(i=0; i<strlen(note); i++){ if(note[i] == keyword[match]) match++; else { if(note[i] == keyword[0]) match = 1; else match = 0; } if(match == keyword_length) return 1; } return 0; }
$ ./main
[DEBUG] uid 1000の34バイトのメモを見つけました
this is a test of multiuser notes
—–[ メモの終わり ]——