Skip to content
Snippets Groups Projects
Commit a5da7c83 authored by Eric Vidal's avatar Eric Vidal :speech_balloon:
Browse files

add @intree feature

parent 6649b940
No related branches found
No related tags found
No related merge requests found
......@@ -275,36 +275,6 @@ This section is *mandatory*. (!)
---
- @name
*Corresponds to the name of the service directory of [s6](https://skarnet.org/software/s6) and [s6-rc](https://skarnet.org/software/s6-rc) programs*.
Name of the service.
mandatory : no
syntax : inline
valid values :
* This field has no effect except for instantiated services. In such case the name must contain the complete name of the frontend service file.
For example, the following is valid:
````
@name = tty@mine-@I
````
where:
````
@name = mine-@I
````
is not for a frontend service file named tty@.
---
- @version
*Without equivalent, this key is unique to 66 tools*.
......@@ -657,6 +627,24 @@ This section is *mandatory*. (!)
**Note** : 66 version must be higher than 0.3.0.1.
- @intree
*Without equivalent, this key is unique to 66 tools*.
mandatory : no
syntax : inline
valid values :
* Any valid seed file name.
The service will automatically be activated at the tree name set in the *@intree* key value.
**Note** : The corresponding seed file *must* exist on your system to be effective.
---
---
## Section: [start]
......@@ -1082,7 +1070,9 @@ This prototype contain all valid section with all valid `key=value` pair.
```
[main]
@type = classic,longrun,bundle,module
@description = ""
@version = 0.0.0
@depends = ()
@optsdepends = ()
@extdepends = ()
......@@ -1098,6 +1088,7 @@ This prototype contain all valid section with all valid `key=value` pair.
@maxdeath =
@down-signal =
@hiercopy = ()
@intree =
[start]
@build = auto,custom
......
......@@ -35,6 +35,7 @@ enum enum_main_e
ENUM_MANDATORY ,
ENUM_TIME ,
ENUM_LOGOPTS ,
ENUM_SEED ,
ENUM_ENDOFKEY
} ;
......@@ -73,6 +74,7 @@ enum enum_key_section_main_e
KEY_MAIN_HIERCOPY ,
KEY_MAIN_SIGNAL ,
KEY_MAIN_FLAGS ,
KEY_MAIN_INTREE ,
KEY_MAIN_ENDOFKEY
} ;
......@@ -242,6 +244,22 @@ enum enum_logopts_e
extern char const *enum_str_logopts[] ;
typedef enum enum_seed_e enum_seed_t, *enum_seed_t_ref ;
enum enum_seed_e
{
SEED_DEPENDS = 0 ,
SEED_REQUIREDBY ,
SEED_ENABLE ,
SEED_ALLOW ,
SEED_DENY ,
SEED_CURRENT ,
SEED_GROUP ,
SEED_SERVICES ,
SEED_ENDOFKEY
} ;
typedef struct enum_all_enum_s enum_all_enum_t, *enum_all_enum_t_ref ;
struct enum_all_enum_s
......@@ -250,6 +268,8 @@ struct enum_all_enum_s
char const **str ;
} ;
extern ssize_t get_enum_by_key_one(char const *str, int const e) ;
extern ssize_t get_enum_by_key(char const *str) ;
extern char const *get_key_by_enum(int const e, int const key) ;
......@@ -291,12 +311,11 @@ static key_description_t const main_section_list[] =
{ .name = &enum_str_key_section_main[KEY_MAIN_TYPE], .id = KEY_MAIN_TYPE, .expected = EXPECT_LINE },
{ .name = &enum_str_key_section_main[KEY_MAIN_VERSION], .id = KEY_MAIN_VERSION, .expected = EXPECT_LINE },
{ .name = &enum_str_key_section_main[KEY_MAIN_DESCRIPTION], .id = KEY_MAIN_DESCRIPTION, .expected = EXPECT_QUOTE },
{ .name = &enum_str_key_section_main[KEY_MAIN_CONTENTS], .id = KEY_MAIN_CONTENTS, .expected = EXPECT_BRACKET },
{ .name = &enum_str_key_section_main[KEY_MAIN_DEPENDS], .id = KEY_MAIN_DEPENDS, .expected = EXPECT_BRACKET },
{ .name = &enum_str_key_section_main[KEY_MAIN_OPTSDEPS], .id = KEY_MAIN_OPTSDEPS, .expected = EXPECT_BRACKET },
{ .name = &enum_str_key_section_main[KEY_MAIN_EXTDEPS], .id = KEY_MAIN_EXTDEPS, .expected = EXPECT_BRACKET },
{ .name = &enum_str_key_section_main[KEY_MAIN_CONTENTS], .id = KEY_MAIN_CONTENTS, .expected = EXPECT_BRACKET },
{ .name = &enum_str_key_section_main[KEY_MAIN_OPTIONS], .id = KEY_MAIN_OPTIONS, .expected = EXPECT_BRACKET },
{ .name = &enum_str_key_section_main[KEY_MAIN_FLAGS], .id = KEY_MAIN_FLAGS, .expected = EXPECT_BRACKET },
{ .name = &enum_str_key_section_main[KEY_MAIN_NOTIFY], .id = KEY_MAIN_NOTIFY, .expected = EXPECT_UINT },
{ .name = &enum_str_key_section_main[KEY_MAIN_USER], .id = KEY_MAIN_USER, .expected = EXPECT_BRACKET },
{ .name = &enum_str_key_section_main[KEY_MAIN_T_FINISH], .id = KEY_MAIN_T_FINISH, .expected = EXPECT_UINT },
......@@ -304,8 +323,10 @@ static key_description_t const main_section_list[] =
{ .name = &enum_str_key_section_main[KEY_MAIN_T_UP], .id = KEY_MAIN_T_UP, .expected = EXPECT_UINT },
{ .name = &enum_str_key_section_main[KEY_MAIN_T_DOWN], .id = KEY_MAIN_T_DOWN, .expected = EXPECT_UINT },
{ .name = &enum_str_key_section_main[KEY_MAIN_DEATH], .id = KEY_MAIN_DEATH, .expected = EXPECT_UINT },
{ .name = &enum_str_key_section_main[KEY_MAIN_SIGNAL], .id = KEY_MAIN_SIGNAL, .expected = EXPECT_UINT },
{ .name = &enum_str_key_section_main[KEY_MAIN_HIERCOPY], .id = KEY_MAIN_HIERCOPY, .expected = EXPECT_BRACKET },
{ .name = &enum_str_key_section_main[KEY_MAIN_SIGNAL], .id = KEY_MAIN_SIGNAL, .expected = EXPECT_UINT },
{ .name = &enum_str_key_section_main[KEY_MAIN_FLAGS], .id = KEY_MAIN_FLAGS, .expected = EXPECT_BRACKET },
{ .name = &enum_str_key_section_main[KEY_MAIN_INTREE], .id = KEY_MAIN_INTREE, .expected = EXPECT_LINE },
{ .name = &enum_str_key_section_main[KEY_MAIN_ENDOFKEY] }
} ;
......
......@@ -496,7 +496,6 @@ int nocheck_toservice(keynocheck *nocheck,int svtype, sv_alltype *service)
return 1 ;
}
/**********************************
* store
* *******************************/
......@@ -615,9 +614,12 @@ int keep_common(sv_alltype *service,keynocheck *nocheck,int svtype)
if (p == -1 && owner)
{
int e = 0 ;
for (int i = 1; i < nb+1; i++)
if (service->user[i] == owner) e = 1 ;
for (int i = 1; i < nb+1; i++) {
if (service->user[i] == owner) {
e = 1 ;
break ;
}
}
if (!e)
log_warnu_return(LOG_EXIT_ZERO,"use the service -- permission denied") ;
}
......@@ -725,6 +727,11 @@ int keep_common(sv_alltype *service,keynocheck *nocheck,int svtype)
return 0 ;
}
break ;
case KEY_MAIN_INTREE:
service->cname.intree = keep.len ;
if (!stralloc_catb(&keep,chval,*chlen + 1))
log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
break ;
default: log_warn_return(LOG_EXIT_ZERO,"unknown key: ",get_key_by_enum(ENUM_KEY_SECTION_MAIN,nocheck->idkey)) ;
}
......@@ -1231,7 +1238,6 @@ int check_valid_runas(keynocheck *ch)
return 1 ;
}
void parse_err(int ierr,keynocheck *check)
{
log_flow() ;
......@@ -1327,3 +1333,32 @@ int get_svtype_from_file(char const *file)
stralloc_free(&tmp) ;
return svtype ;
}
int get_svintree(sv_alltype *sv_before, char const *contents)
{
log_flow() ;
int r ;
stralloc sa = STRALLOC_ZERO ;
if (!auto_stra(&sa,contents)) goto err ;
/** @intree may not exist */
r = sastr_find(&sa,get_key_by_enum(ENUM_KEY_SECTION_MAIN,KEY_MAIN_INTREE)) ;
if (r == -1) { sv_before->cname.intree == -1 ; goto freed ; }
if (!environ_get_val_of_key(&sa,get_key_by_enum(ENUM_KEY_SECTION_MAIN,KEY_MAIN_INTREE))) goto err ;
if (!sastr_clean_element(&sa)) goto err ;
sv_before->cname.intree = keep.len ;
if (!sastr_add_string(&keep, sa.s))
goto err ;
freed:
stralloc_free(&sa) ;
return 1 ;
err:
stralloc_free(&sa) ;
return 0 ;
}
......@@ -49,6 +49,7 @@ char const *enum_str_key_section_main[] = {
"@hiercopy" ,
"@down-signal" ,
"@flags" ,
"@intree" ,
0
} ;
......@@ -145,11 +146,34 @@ char const *enum_str_time[] = {
char const *enum_str_logopts[] = {
"producer-for" ,
"consumer-for" ,
"pipeline-name" ,
0
} ;
char const *enum_str_seed[] = {
"depends" ,
"requiredby" ,
"enable" ,
"allow" ,
"deny" ,
"current" ,
"group" ,
"services" ,
/**
*
*
* rajouter owner qui correspond detenteur de la commande lancer
* cela permet de faire la difference entre allow et deny list
* et le vrai propriétaire de l'arbre
*
*
* */
0
} ;
enum_all_enum_t enum_all[] = {
[ENUM_SECTION] = { .enum_all = SECTION_ENDOFKEY - ENUM_START, .str = enum_str_section } ,
......@@ -166,6 +190,7 @@ enum_all_enum_t enum_all[] = {
[ENUM_MANDATORY] = { .enum_all = MANDATORY_ENDOFKEY - ENUM_START , .str = enum_str_mandatory } ,
[ENUM_TIME] = { .enum_all = TIME_ENDOFKEY - ENUM_START , .str = enum_str_time } ,
[ENUM_LOGOPTS] = { .enum_all = LOGOPTS_ENDOFKEY - ENUM_START , .str = enum_str_logopts } ,
[ENUM_SEED] = { .enum_all = SEED_ENDOFKEY - ENUM_START , .str = enum_str_seed } ,
[ENUM_ENDOFKEY] = { 0 }
} ;
......
/*
* tree_seed.c
*
* Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
*
* All rights reserved.
*
* This file is part of Obarun. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution.
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file./
*/
#include <66/tree.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>//getuid
#include <oblibs/string.h>
#include <oblibs/files.h>
#include <oblibs/log.h>
#include <oblibs/environ.h>
#include <oblibs/sastr.h>
#include <oblibs/types.h>
#include <skalibs/stralloc.h>
#include <skalibs/djbunix.h>
#include <66/enum.h>
#include <66/utils.h>
#include <66/config.h>
stralloc saseed = STRALLOC_ZERO ;
void tree_seed_free(void)
{
stralloc_free(&saseed) ;
}
static ssize_t tree_seed_get_key(char *table,char const *str)
{
ssize_t pos = -1 ;
pos = get_len_until(str,'=') ;
if (pos == -1)
return -1 ;
auto_strings(table,str) ;
table[pos] = 0 ;
pos++ ; // remove '='
return pos ;
}
int tree_seed_parse_file(ss_tree_seed_t *seed, char const *seedpath)
{
log_flow() ;
int r ;
stralloc sa = STRALLOC_ZERO ;
size_t pos = 0 ;
size_t filesize=file_get_size(seedpath) ;
if (!filesize) {
log_warn(seedpath," is empty") ;
goto err ;
}
r = openreadfileclose(seedpath, &sa, filesize) ;
if(!r) {
log_warnusys("open ", seedpath) ;
goto err ;
}
/** ensure that we have an empty line at the end of the string*/
if (!auto_stra(&sa,"\n"))
log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
if (!environ_get_clean_env(&sa)) {
log_warnu("clean seed file: ", seedpath) ;
goto err ;
}
if (!sastr_split_string_in_nline(&sa))
goto err ;
FOREACH_SASTR(&sa, pos) {
char *line = sa.s + pos, *key = 0, *val = 0 ;
size_t len = strlen(line) ;
char tmp[len + 1] ;
r = tree_seed_get_key(tmp, line) ;
/** should never happens */
if (r == -1) {
log_warn("invalid format of key: ",line," -- please make a bug report") ;
goto err ;
}
key = tmp ;
val = line + r ;
ssize_t e = get_enum_by_key(key) ;
switch (e) {
case SEED_DEPENDS :
seed->depends = saseed.len ;
if (!sastr_add_string(&saseed, val))
goto err ;
seed->nopts++ ;
break ;
case SEED_REQUIREDBY :
seed->requiredby = saseed.len ;
if (!sastr_add_string(&saseed, val))
goto err ;
seed->nopts++ ;
break ;
case SEED_ENABLE :
if (!strcmp(val,"true") || !strcmp(val,"True"))
seed->enabled = 1 ;
seed->nopts++ ;
break ;
case SEED_ALLOW :
seed->allow = saseed.len ;
if (!sastr_add_string(&saseed, val))
goto err ;
seed->nopts++ ;
break ;
case SEED_DENY :
seed->deny = saseed.len ;
if (!sastr_add_string(&saseed, val))
goto err ;
seed->nopts++ ;
break ;
case SEED_CURRENT :
if (!strcmp(val,"true") || !strcmp(val,"True"))
seed->current = 1 ;
seed->nopts++ ;
break ;
case SEED_GROUP :
if (strcmp(val,"boot") && strcmp(val,"admin") && strcmp(val,"user")) {
log_warn("invalid group: ", val) ;
goto err ;
}
seed->group = saseed.len ;
if (!sastr_add_string(&saseed, val))
goto err ;
seed->nopts++ ;
break ;
case SEED_SERVICES :
{
stralloc sv = STRALLOC_ZERO ;
if (!sastr_clean_string_wdelim(&sv, val, ',') ||
!sastr_rebuild_in_oneline(&sv)) {
log_warnu("clean service list") ;
goto err ;
}
seed->services = saseed.len ;
if (!sastr_add_string(&saseed, sv.s))
goto err ;
seed->nopts++ ;
break ;
}
default :
log_warn("unknown key: ", key, " -- ignoring") ;
break ;
}
}
stralloc_free(&sa) ;
return 1 ;
err:
stralloc_free(&sa) ;
return 0 ;
}
/** @Return -1 bad format e.g want REG get DIR
* @Return 0 fail
* @Return success */
static int tree_seed_file_isvalid(char const *seedpath, char const *treename)
{
log_flow() ;
int r ;
size_t slen = strlen(seedpath), tlen = strlen(treename) ;
char seed[slen + tlen + 1] ;
auto_strings(seed, seedpath, treename) ;
r = scan_mode(seed, S_IFREG) ;
return r ;
}
int tree_seed_resolve_path(stralloc *sa, char const *seed)
{
log_flow() ;
int r ;
char *src = 0 ;
uid_t uid = getuid() ;
if (!uid) {
src = SS_SEED_ADMDIR ;
} else {
if (!set_ownerhome(sa, uid))
log_warnusys_return(LOG_EXIT_ZERO, "set home directory") ;
if (!auto_stra(sa, SS_SEED_USERDIR))
log_warnsys_return(LOG_EXIT_ZERO, "stralloc") ;
src = sa->s ;
}
r = tree_seed_file_isvalid(src, seed) ;
if (r == -1)
return 0 ;
if (!r) {
/** yeah double check because we can come from !uid */
src = SS_SEED_ADMDIR ;
r = tree_seed_file_isvalid(src, seed) ;
if (r == -1)
return 0 ;
if (!r) {
src = SS_SEED_SYSDIR ;
r = tree_seed_file_isvalid(src, seed) ;
if (r != 1)
return 0 ;
}
}
sa->len = 0 ;
if (!auto_stra(sa,src, seed))
log_warnsys_return(LOG_EXIT_ZERO, "stralloc") ;
return 1 ;
}
int tree_seed_isvalid(char const *seed)
{
int e = 1 ;
stralloc src = STRALLOC_ZERO ;
if (!tree_seed_resolve_path(&src, seed))
e = 0 ;
stralloc_free(&src) ;
return e ;
}
int tree_seed_ismandatory(ss_tree_seed_t *seed, uint8_t check_service)
{
log_flow() ;
uid_t uid = getuid() ;
size_t pos = 0 ;
stralloc sv = STRALLOC_ZERO ;
char *group = saseed.s + seed->group ;
char *service = saseed.s + seed->services ;
if (!uid && (!strcmp(group, "user"))) {
log_warn("Only regular user can use this seed") ;
goto err ;
} else if (uid && (!strcmp(group, "root"))) {
log_warn("Only root user can use this seed") ;
goto err ;
}
if (!strcmp(saseed.s + seed->name , "boot") && seed->enabled) {
log_warn("enable was asked for a tree on group boot -- ignoring enable request") ;
seed->enabled = 0 ;
}
if (check_service) {
stralloc sasrc = STRALLOC_ZERO ;
if (!stralloc_cats(&sv, service) ||
!sastr_clean_element(&sv)) {
log_warnu("clean service list") ;
stralloc_free(&sasrc) ;
goto err ;
}
FOREACH_SASTR(&sv, pos) {
char *s = sv.s + pos ;
/** ss_resolve_src already warn user */
if (!ss_resolve_src_path(&sasrc,s, uid, 0)) {
stralloc_free(&sasrc) ;
goto err ;
}
}
stralloc_free(&sasrc) ;
}
stralloc_free(&sv) ;
return 1 ;
err:
stralloc_free(&sv) ;
return 0 ;
}
/** Return 0 on fail
* Return 1 if tree need to be created
* Return 2 if tree already exist */
int tree_seed_setseed(ss_tree_seed_t *seed, char const *treename, uint8_t check_service)
{
log_flow() ;
stralloc src = STRALLOC_ZERO ;
if (!tree_seed_resolve_path(&src, treename))
goto err ;
seed->name = saseed.len ;
if (!sastr_add_string(&saseed, treename))
goto err ;
if (!tree_seed_parse_file(seed, src.s) ||
!tree_seed_ismandatory(seed, check_service))
goto err ;
stralloc_free(&src) ;
return 1 ;
err:
stralloc_free(&src) ;
return 0 ;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment