>From f4118bdc56da613046caa6e19981ca4f9cd9cf43 Mon Sep 17 00:00:00 2001 From: Markus Steinborn Date: Tue, 17 Dec 2013 21:26:21 +0100 Subject: [PATCH 1/3] tar extract should use the 4th field (discussed in point 2) in presence of "-numeric-owner". This together with point (2) enabled users to restore an backup created without numeric owner option on a clean hard disc without passwd entries for the users (let's assume that /etc/passwd is contained in the archive so the operation makes sense). --- src/xattrs.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 252 insertions(+), 1 deletion(-) diff --git a/src/xattrs.c b/src/xattrs.c index 8e56168..634eeaf 100644 --- a/src/xattrs.c +++ b/src/xattrs.c @@ -191,7 +191,7 @@ fixup_extra_acl_fields (char *ptr) src += strcspn (src, "\n,"); if ((*src == '\n') || (*src == ',')) - *dst++ = *src++; /* also done when dst == src, but that's ok */ + *(dst++) = *src++; /* also done when dst == src, but that's ok */ } if (src != dst) *dst = 0; @@ -199,6 +199,253 @@ fixup_extra_acl_fields (char *ptr) return ptr; } +void acl_check_ids(char* acltext, char* infotext) +{ + int state = 1; + char *src = acltext; + char *dst = infotext; + char username[100], acc[4], userid[20]; + char *tmp = 0; + + + while (1) + { + if (state == 1) + { + switch (*src) + { + case ' ': + case 13: + case 10: + break; + + case '#': + state = 5; + break; + + case 'u': + state = 2; + *(dst++) = 'u'; + break; + case 'g': + state = 3; + *(dst++) = 'g'; + break; + case 'o': + state = 4; + *(dst++) = 'o'; + break; + case 'm': + state = 22; + *(dst++) = 'm'; + break; + default: + state = 0; + } + } + else if (state == 5) + { + if (*src == 13) state = 1; + else if (*src == 0) { state = 20; *tmp = 0; continue; } + } + + else if (state == 2) + { + if (*src == ':') { state = 17; *(dst++) = ':'; *username=0; *acc=0; *userid=0; tmp=username; } + else if (*src == 's') state = 6; + else state = 0; + } + else if (state == 6) + { + if (*src == 'e') state = 7; + else state = 0; + } + else if (state == 7) + { + if (*src == 'r') state = 8; + else state = 0; + } + else if (state == 8) + { + if (*src == ':') { state = 17; *(dst++) = ':'; *username=0; *acc=0; *userid=0; tmp=username; } + else state = 0; + } + + else if (state == 3) + { + if (*src == ':') { state = 17; *(dst++) = ':'; *username=0; *acc=0; *userid=0; tmp=username; } + else if (*src == 'r') state = 9; + else state = 0; + } + else if (state == 9) + { + if (*src == 'o') state = 10; + else state = 0; + } + else if (state == 10) + { + if (*src == 'u') state = 11; + else state = 0; + } + else if (state == 11) + { + if (*src == 'p') state = 12; + else state = 0; + } + else if (state == 12) + { + if (*src == ':') { state = 17; *(dst++) = ':'; *username=0; *acc=0; *userid=0; tmp=username; } + else state = 0; + } + + else if (state == 4) + { + if (*src == ':') { state = 17; *(dst++) = ':'; *username=0; *acc=0; *userid=0; tmp=username; } + else if (*src == 't') state = 13; + else state = 0; + } + else if (state == 13) + { + if (*src == 'h') state = 14; + else state = 0; + } + else if (state == 14) + { + if (*src == 'e') state = 15; + else state = 0; + } + else if (state == 15) + { + if (*src == 'r') state = 16; + else state = 0; + } + else if (state == 16) + { + if (*src == ':') { state = 17; *(dst++) = ':'; *username=0; *acc=0; *userid=0; tmp=username; } + else state = 0; + } + + else if (state == 22) + { + if (*src == ':') { state = 17; *(dst++) = ':'; *username=0; *acc=0; *userid=0; tmp=username; } + else if (*src == 'a') state = 23; + else state = 0; + } + else if (state == 23) + { + if (*src == 's') state = 24; + else state = 0; + } + else if (state == 24) + { + if (*src == 'k') state = 25; + else state = 0; + } + else if (state == 25) + { + if (*src == ':') { state = 17; *(dst++) = ':'; *username=0; *acc=0; *userid=0; tmp=username; } + else state = 0; + } + + /* 2nd field */ + else if (state == 17) + { + if (*src == ':') { state = 18; *tmp = 0; tmp = acc; } + else if (*src == 0) { state = 0; *tmp = 0; } + else *(tmp++) = *src; + } + + /* 3rd field */ + else if (state == 18) + { + if (*src == ' ') { state = 20; *tmp = 0; } + else if (*src == '\n') { state = 20; *tmp = 0; } + else if (*src == ',') { state = 20; *tmp = 0; } + else if (*src == ':') { state = 19; *tmp = 0; tmp = userid; } + else if (*src == 0) { state = 20; *tmp = 0; continue; } + else *(tmp++) = *src; + } + + /* 4th field */ + else if (state == 19) + { + if (*src == ' ') { state = 20; *tmp = 0; } + else if (*src == '\n') { state = 20; *tmp = 0; } + else if (*src == ',') { state = 20; *tmp = 0; } + else if (*src == ':') { state = 20; *tmp = 0; } + else if (*src == 0) { state = 20; *tmp = 0; continue; } + else *(tmp++) = *src; + } + + /* End of "line" */ + else if (state == 20) + { + state = 21; + if ( numeric_owner_option && *userid ) + tmp = userid; + else + tmp = username; + while (*tmp) *(dst++) = *(tmp++); + *(dst++) = ':'; + tmp = acc; + while (*tmp) *(dst++) = *(tmp++); + continue; + } + + else if (state == 21) + { + switch (*src) + { + case ' ': + case 13: + case 10: + break; + + case '#': + state = 5; + break; + + case 'u': + state = 2; + *(dst++) = ','; + *(dst++) = 'u'; + break; + case 'g': + state = 3; + *(dst++) = ','; + *(dst++) = 'g'; + break; + case 'o': + state = 4; + *(dst++) = ','; + *(dst++) = 'o'; + break; + case 'm': + state = 22; + *(dst++) = ','; + *(dst++) = 'm'; + break; + + case 0: + break; + + default: + state = 0; + } + } + + if (!state || !*src) + break; + else + ++src; + } + + *dst = 0; + if (!state) + *infotext = 0; +} + +/* "system.posix_acl_access" */ /* Set the "system.posix_acl_access/system.posix_acl_default" extended attribute. Called only when acls_option > 0. */ static void @@ -213,6 +460,10 @@ xattrs__acls_set (struct tar_stat_info const *st, /* assert (strlen (ptr) == len); */ ptr = fixup_extra_acl_fields (ptr); acl = acl_from_text (ptr); + char* tmp = malloc(len+1); + acl_check_ids(ptr,tmp); + acl = acl_from_text (tmp); + free(tmp); } else if (def) { -- 2.7.4