全てのユーザには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
—–[ メモの終わり ]——