2 * Copyright (C) 2006 International Business Machines Corp.
3 * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
4 * Trevor Highland <trevor.highland@gmail.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
31 #include "../include/ecryptfs.h"
32 #include "../include/decision_graph.h"
34 int stack_push(struct val_node **head, void *val)
36 struct val_node *node = malloc(sizeof(struct val_node));
50 int stack_pop(struct val_node **head)
52 struct val_node *tmp = (*head)->next;
60 int stack_pop_val(struct val_node **head, void **val)
63 struct val_node *tmp = (*head)->next;
73 int free_name_val_pairs(struct ecryptfs_name_val_pair *pair)
75 struct ecryptfs_name_val_pair *next;
89 int add_transition_node_to_param_node(struct param_node *param_node,
90 struct transition_node *trans_node)
94 if (param_node->num_transitions >= MAX_NUM_TRANSITIONS) {
95 syslog(LOG_ERR, "Too many transitions on node with primary "
96 "alias [%s]\n", param_node->mnt_opt_names[0]);
100 memcpy(&(param_node->tl[param_node->num_transitions++]),
101 trans_node, sizeof(*trans_node));
108 * set_exit_param_node_for_node
110 * Sets all NULL next_token's to exit_param_node
112 int set_exit_param_node_for_node(struct param_node *param_node,
113 struct param_node *exit_param_node,
119 for (i = 0; i < param_node->num_transitions; i++)
120 if (param_node->tl[i].next_token == NULL) {
121 param_node->tl[i].val = "default";
122 param_node->tl[i].pretty_val = "default";
123 param_node->tl[i].next_token = exit_param_node;
124 } else if (recursive) {
125 rc = set_exit_param_node_for_node(
126 param_node->tl[i].next_token,
136 * Sets the exit param node for all NULL transitions throughout an
139 int ecryptfs_set_exit_param_on_graph(struct param_node *param_node,
140 struct param_node *exit_param_node)
142 return set_exit_param_node_for_node(param_node, exit_param_node, 1);
145 void ecryptfs_destroy_nvp(struct ecryptfs_name_val_pair *nvp)
150 int ecryptfs_delete_nvp(struct ecryptfs_name_val_pair *nvp_head,
151 struct ecryptfs_name_val_pair *nvp)
156 if (nvp_head->next == nvp) {
157 nvp_head->next = nvp->next;
158 ecryptfs_destroy_nvp(nvp);
161 nvp_head = nvp_head->next;
170 * @ctx: The current eCryptfs library context
171 * @next: Set to the param_node that the transition engine determines
173 * @current: The current param_node from which we are transitioning
174 * @nvp_head: The name-value pair list that contains name-value pairs
175 * specified on the command line or provided via the
176 * .ecryptfsrc file. Whenever a param node needs a value,
177 * the decision graph logic first scans this list for a
178 * corresponding name-value pair
179 * @mnt_params: Head of mount option stack that the callback functions
180 * for the transition nodes in the param node populate
181 * @foo: An arbitrary data structure that the transition node callback
182 * functions create, reference, and destroy
184 * This function needs to compare transition nodes to options.
185 * It is currently comparing them to values provided to options.
186 * i.e., each transition is an option; this is incorrect.
188 int do_transition(struct ecryptfs_ctx *ctx, struct param_node **next,
189 struct param_node *current,
190 struct ecryptfs_name_val_pair *nvp_head,
191 struct val_node **mnt_params, void **foo)
193 static int repeated = 0;
194 static struct param_node *lastnode = NULL;
197 if (current != lastnode)
202 for (i = 0; i < current->num_transitions; i++) {
203 struct transition_node *tn = ¤t->tl[i];
204 struct ecryptfs_name_val_pair *nvp = nvp_head->next;
206 if (tn->val && current->val
207 && strcmp(current->val, tn->val) == 0) {
209 if (tn->trans_func) {
210 rc = tn->trans_func(ctx, current,
213 if ((*next = tn->next_token)) {
214 if (ecryptfs_verbosity) {
216 "Transitioning from [%p]; name "
217 "= [%s] to [%p]; name = [%s] "
218 "per transition node's "
219 "next_token\n", current,
220 current->mnt_opt_names[0],
222 (*next)->mnt_opt_names[0]);
229 int trans_func_tok_id = NULL_TOK;
231 if (tn->val && strcmp(nvp->name, tn->val)) {
237 tn->trans_func(ctx, current,
239 if (trans_func_tok_id == MOUNT_ERROR) {
240 return trans_func_tok_id;
242 if (trans_func_tok_id == DEFAULT_TOK) {
243 if ((*next = tn->next_token))
247 } else if (trans_func_tok_id == NULL_TOK) {
248 if ((*next = tn->next_token))
256 for (i = 0; i < current->num_transitions; i++) {
257 struct transition_node *tn = ¤t->tl[i];
259 if (tn->val && strcmp("default", tn->val) == 0) {
260 int trans_func_tok_id = NULL_TOK;
264 tn->trans_func(ctx, current,
266 if (trans_func_tok_id == WRONG_VALUE) {
267 if (ctx->verbosity ||
268 (current->flags & STDIN_REQUIRED)) {
278 if (trans_func_tok_id == MOUNT_ERROR ||
279 trans_func_tok_id < 0)
280 return trans_func_tok_id;
281 if ((*next = tn->next_token))
286 if (current->num_transitions)
292 * Try to find one of the aliases for this node in the list of
293 * name-value pairs. If found, set the value from that element in the
296 * Returns non-zero on error condition
298 static int retrieve_val(int *value_retrieved,
299 struct ecryptfs_name_val_pair *nvp_head,
300 struct param_node *node)
302 int i = node->num_mnt_opt_names;
305 if (ecryptfs_verbosity)
306 syslog(LOG_INFO, "%s: Called on node [%s]\n", __FUNCTION__,
307 node->mnt_opt_names[0]);
308 (*value_retrieved) = 0;
310 struct ecryptfs_name_val_pair *temp = nvp_head->next;
314 if (strcmp(temp->name, node->mnt_opt_names[i]) == 0
315 && !(temp->flags & ECRYPTFS_PROCESSED)) {
316 if (ecryptfs_verbosity)
317 syslog(LOG_INFO, "From param_node = "
318 "[%p]; mnt_opt_names[0] = [%s]"
320 "ECRYPTFS_PROCESSED to nvp with "
321 "nvp->name = [%s]\n",
322 node, node->mnt_opt_names[0],
324 /* Prevent the same name/value pair
325 * from being consumed twice */
326 temp->flags |= ECRYPTFS_PROCESSED;
328 && (strcmp(temp->value, "(null)") != 0)) {
329 if (asprintf(&node->val, "%s",
330 temp->value) == -1) {
335 node->flags |= PARAMETER_SET;
336 (*value_retrieved) = 1;
342 if (node->default_val && (strcmp(node->default_val, "NULL") != 0)) {
343 if (asprintf(&node->val, "%s", node->default_val) == -1) {
347 if (ecryptfs_verbosity)
348 syslog(LOG_INFO, "%s: Value retrieved from "
349 "node->default_val = [%s]\n", __FUNCTION__,
351 (*value_retrieved) = 1;
359 * This function can prompt the user and/or check some list of values
360 * to get what it needs. Caller must free node->val if it winds up
363 static int alloc_and_get_val(struct ecryptfs_ctx *ctx, struct param_node *node,
364 struct ecryptfs_name_val_pair *nvp_head)
374 if (ecryptfs_verbosity)
375 syslog(LOG_INFO, "%s: Called on node->mnt_opt_names[0] = [%s]",
376 __FUNCTION__, node->mnt_opt_names[0]);
378 if (ecryptfs_verbosity)
379 syslog(LOG_INFO, "%s: node->val already set to [%s]\n",
380 __FUNCTION__, node->val);
383 rc = retrieve_val(&value_retrieved, nvp_head, node);
385 syslog(LOG_ERR, "%s: Error attempting to retrieve value; "
386 "rc = [%d]\n", __FUNCTION__, rc);
389 if (value_retrieved) {
390 if (ecryptfs_verbosity)
392 "%s: Value retrieved from default_val or from "
393 "parameter list; returning\n",
395 if (!(node->flags & ECRYPTFS_ALLOW_IMPLICIT_TRANSITION
396 && node->flags & ECRYPTFS_IMPLICIT_OVERRIDE_DEFAULT))
399 if (node->flags & ECRYPTFS_ALLOW_IMPLICIT_TRANSITION
400 && !(node->flags & ECRYPTFS_NO_AUTO_TRANSITION)) {
401 for (i = 0; i < node->num_transitions; i++) {
402 if (node->tl[i].next_token)
403 rc = retrieve_val(&value_retrieved, nvp_head,
404 node->tl[i].next_token);
406 syslog(LOG_ERR, "%s: Error attempting to "
407 "retrieve value; rc = [%d]\n",
411 if (value_retrieved) {
412 if (ecryptfs_verbosity)
414 "%s: Value retrieved from "
415 "default_val or from parameter "
416 "list for successive "
417 "node at transition slot [%d]; "
418 "returning\n", __FUNCTION__, i);
419 rc = asprintf(&node->val, "%s",
420 node->tl[i].next_token->mnt_opt_names[0]);
430 if (node->flags & ECRYPTFS_PARAM_FLAG_NO_VALUE) {
431 if (ecryptfs_verbosity)
433 "%s: ECRYPTFS_PARAM_FLAG_NO_VALUE set\n",
437 if (ctx->verbosity == 0 && !(node->flags & STDIN_REQUIRED)) {
438 if (ecryptfs_verbosity)
439 syslog(LOG_INFO, "%s: ctx->verbosity == 0 and "
440 "STDIN_REQUIRED not set\n", __FUNCTION__);
443 if ((node->flags & PARAMETER_SET) && !(node->flags & STDIN_REQUIRED)) {
444 if (ecryptfs_verbosity)
445 syslog(LOG_INFO, "%s: PARAMETER_SET and "
446 "STDIN_REQUIRED not set\n", __FUNCTION__);
449 if (ctx->get_string) {
450 if (ecryptfs_verbosity)
451 syslog(LOG_INFO, "%s: ctx->get_string defined\n",
453 if (node->flags & DISPLAY_TRANSITION_NODE_VALS) {
454 struct prompt_elem pe_head;
455 struct prompt_elem *pe;
460 if (ecryptfs_verbosity)
461 syslog(LOG_INFO, "%s: DISPLAY_TRANSITION_NODE_"
462 "VALS set\n", __FUNCTION__);
463 memset(&pe_head, 0, sizeof(pe_head));
465 if ((node->num_transitions == 1)
467 & ECRYPTFS_PARAM_FORCE_DISPLAY_NODES)) {
468 if (asprintf(&(node->val), "%s",
469 node->tl[0].val) == -1) {
476 pe->next = malloc(sizeof(*pe));
482 memset(pe, 0, sizeof(*pe));
483 rc = asprintf(&pe->str, "%s: \n", node->prompt);
489 for (i = 0; i < node->num_transitions; i++) {
490 pe->next = malloc(sizeof(*pe));
496 memset(pe, 0, sizeof(*pe));
497 if (node->flags & ECRYPTFS_DISPLAY_PRETTY_VALS)
498 rc = asprintf(&pe->str, " %d) %s\n",
500 node->tl[i].pretty_val);
502 rc = asprintf(&pe->str, " %d) %s\n",
511 pe->next = malloc(sizeof(*pe));
517 memset(pe, 0, sizeof(*pe));
518 if (node->suggested_val)
519 rc = asprintf(&pe->str, "Selection [%s]",
520 node->suggested_val);
521 else if (node->default_val)
522 rc = asprintf(&pe->str, "Selection [%s]",
525 rc = asprintf(&pe->str, "Selection");
531 /* Convert prompt_elem linked list into
532 * single prompt string */
536 prompt_len += strlen(pe->str);
541 prompt = malloc(prompt_len);
548 struct prompt_elem *pe_tmp;
550 memcpy(&prompt[i], pe->str, strlen(pe->str));
551 i += strlen(pe->str);
559 if ((rc = (ctx->get_string)
560 (&(node->val), prompt,
562 & ECRYPTFS_PARAM_FLAG_ECHO_INPUT)))) {
566 val = atoi(node->val);
567 if (val > 0 && val <= node->num_transitions) {
569 if (asprintf(&(node->val), "%s",
570 node->tl[val - 1].val) == -1) {
577 if (node->val[0] == '\0') {
578 if (!node->suggested_val)
580 rc = asprintf(&node->val, "%s",
581 node->suggested_val);
589 for (i = 0; i < node->num_transitions; i++) {
590 if (strcmp(node->val, node->tl[i].val)
604 if (ecryptfs_verbosity)
605 syslog(LOG_INFO, "%s: DISPLAY_TRANSITION_NODE_"
606 "VALS not set\n", __FUNCTION__);
608 if (++tries > 3) return EINVAL;
609 if (node->suggested_val)
610 rc = asprintf(&prompt, "%s [%s]", node->prompt,
611 node->suggested_val);
613 rc = asprintf(&prompt, "%s", node->prompt);
619 if (ecryptfs_verbosity)
621 "%s: node->mnt_opt_names[0] = [%s]\n; "
622 "node->flags = [0x%.8x]\n",
624 node->mnt_opt_names[0], node->flags);
625 rc = (ctx->get_string)
626 (&(node->val), prompt,
628 & ECRYPTFS_PARAM_FLAG_ECHO_INPUT));
632 if (node->val[0] == '\0' &&
633 (node->flags & ECRYPTFS_NONEMPTY_VALUE_REQUIRED)) {
634 fprintf(stderr,"Wrong input, non-empty value "
638 if (node->flags & VERIFY_VALUE) {
639 rc = asprintf(&verify_prompt, "Verify %s",
643 rc = (ctx->get_string)
644 (&verify, verify_prompt,
646 & ECRYPTFS_PARAM_FLAG_ECHO_INPUT));
650 rc = strcmp(verify, node->val);
658 if (node->val[0] == '\0') {
660 node->val = node->suggested_val;
665 if (ecryptfs_verbosity)
666 syslog(LOG_INFO, "%s: ctx->get_string not defined",
674 static void get_verbosity(struct ecryptfs_name_val_pair *nvp_head,
677 struct ecryptfs_name_val_pair *temp = nvp_head->next;
681 if (strcmp(temp->name, "verbosity") == 0) {
682 *verbosity = atoi(temp->value);
690 int eval_param_tree(struct ecryptfs_ctx *ctx, struct param_node *node,
691 struct ecryptfs_name_val_pair *nvp_head,
692 struct val_node **mnt_params)
697 get_verbosity(nvp_head, &(ctx->verbosity));
699 if (ecryptfs_verbosity) {
702 syslog(LOG_INFO, "%s: Calling alloc_and_get_val() on "
703 "node = [%p]; node->mnt_opt_names[0] = [%s]\n",
704 __FUNCTION__, node, node->mnt_opt_names[0]);
705 for (i = 0; i < node->num_transitions; i++) {
707 "%s: node->tl[%d].val = [%s]\n",
708 __FUNCTION__, i, node->tl[i].val);
711 if ((rc = alloc_and_get_val(ctx, node, nvp_head)))
713 } while (!(rc = do_transition(ctx, &node, node, nvp_head,
718 int ecryptfs_eval_decision_graph(struct ecryptfs_ctx *ctx,
719 struct val_node **mnt_params,
720 struct param_node *root_node,
721 struct ecryptfs_name_val_pair *nvp_head) {
724 memset(*mnt_params, 0, sizeof(struct val_node));
725 rc = eval_param_tree(ctx, root_node, nvp_head, mnt_params);
726 if ((rc > 0) && (rc != MOUNT_ERROR))
732 static void print_whitespace(FILE *file_stream, int depth)
736 for (i = 0; i < depth; i++)
737 fprintf(file_stream, " ");
740 void ecryptfs_dump_param_node(FILE *file_stream,
741 struct param_node *param_node, int depth,
744 void ecryptfs_dump_transition_node(FILE *file_stream,
745 struct transition_node *trans_node,
746 int depth, int recursive)
748 print_whitespace(file_stream, depth);
749 fprintf(file_stream, "---------------\n");
750 print_whitespace(file_stream, depth);
751 fprintf(file_stream, "transition_node\n");
752 print_whitespace(file_stream, depth);
753 fprintf(file_stream, "---------------\n");
754 print_whitespace(file_stream, depth);
755 fprintf(file_stream, "val = [%s]\n", trans_node->val);
756 print_whitespace(file_stream, depth);
757 fprintf(file_stream, "next_token = [%p]\n", trans_node->next_token);
758 if (recursive && trans_node->next_token)
759 ecryptfs_dump_param_node(file_stream, trans_node->next_token,
760 depth + 1, recursive);
761 print_whitespace(file_stream, depth);
762 fprintf(file_stream, "---------------\n");
765 void ecryptfs_dump_param_node(FILE *file_stream,
766 struct param_node *param_node, int depth,
771 print_whitespace(file_stream, depth);
772 fprintf(file_stream, "----------\n");
773 print_whitespace(file_stream, depth);
774 fprintf(file_stream, "param_node\n");
775 print_whitespace(file_stream, depth);
776 fprintf(file_stream, "----------\n");
777 print_whitespace(file_stream, depth);
778 fprintf(file_stream, "mnt_opt_names[0] = [%s]\n",
779 param_node->mnt_opt_names[0]);
780 print_whitespace(file_stream, depth);
781 fprintf(file_stream, "num_transitions = [%d]\n",
782 param_node->num_transitions);
783 for (i = 0; i < param_node->num_transitions; i++) {
784 print_whitespace(file_stream, depth);
785 fprintf(file_stream, "transition node [%d]:\n", i);
786 ecryptfs_dump_transition_node(file_stream, ¶m_node->tl[i],
787 depth + 1, recursive);
789 print_whitespace(file_stream, depth);
790 fprintf(file_stream, "----------\n");
794 void ecryptfs_dump_decision_graph(FILE *file_stream,
795 struct param_node *param_node, int depth)
797 ecryptfs_dump_param_node(file_stream, param_node, depth, 1);
800 int ecryptfs_insert_params(struct ecryptfs_name_val_pair *nvp,
801 struct param_node *param_node)
804 struct ecryptfs_name_val_pair *cursor = nvp;
808 cursor = cursor->next;
809 for (i = 0; i < param_node->num_mnt_opt_names; i++) {
811 malloc(sizeof(struct ecryptfs_name_val_pair))) == NULL) {
812 syslog(LOG_ERR, "Error attempting to allocate nvp\n");
816 cursor = cursor->next;
818 if ((rc = asprintf(&cursor->name, "%s",
819 param_node->mnt_opt_names[i])) == -1) {
820 syslog(LOG_ERR, "Error attempting to allocate nvp "
821 "entry for param_node->mnt_opt_names[%d] = "
822 "[%s]\n", i, param_node->mnt_opt_names[i]);
828 for (i = 0; i < param_node->num_transitions; i++) {
829 if (param_node->tl[i].next_token == NULL)
832 ecryptfs_insert_params(cursor,
833 param_node->tl[i].next_token))) {
834 syslog(LOG_ERR, "Error inserting param; param_node->"
835 "mnt_opt_names[0] = [%s]; transition token "
836 "index = [%d]\n", param_node->mnt_opt_names[0],
846 * ecryptfs_insert_params_in_subgraph
848 * For all of the parameter nodes in the subgraph, append a name/value
849 * pair to the list with the nvp name set to the parameter node opt
852 int ecryptfs_insert_params_in_subgraph(struct ecryptfs_name_val_pair *nvp,
853 struct transition_node *trans_node)
857 if (trans_node->next_token)
858 rc = ecryptfs_insert_params(nvp, trans_node->next_token);
863 static struct flag_map {
866 } nvp_flags_to_param_flags_map[] = {
867 {.flag_src = ECRYPTFS_PARAM_FLAG_ECHO_INPUT,
868 .flag_dst = ECRYPTFS_PARAM_FLAG_ECHO_INPUT},
870 #define ECRYPTFS_NVP_FLAGS_TO_PARAM_FLAGS_MAP_SIZE 1
872 static int ecryptfs_map_flags(uint32_t *param_flags, uint32_t nvp_flags)
876 for (i = 0; i < ECRYPTFS_NVP_FLAGS_TO_PARAM_FLAGS_MAP_SIZE; i++)
877 if (nvp_flags & nvp_flags_to_param_flags_map[i].flag_src) {
878 if (ecryptfs_verbosity)
879 syslog(LOG_INFO, "Setting flag [0x%.8x]\n",
880 nvp_flags_to_param_flags_map[i].flag_dst);
882 nvp_flags_to_param_flags_map[i].flag_dst;
887 struct ecryptfs_subgraph_ctx {
888 struct ecryptfs_key_mod *key_mod;
889 struct val_node head_val_node;
893 * ecryptfs_enter_linear_subgraph_tf
897 * @foo: Pointer memory in the activation record for
898 * eval_param_tree(). Transition node callback functions hang
899 * whatever they want off this pointer. In the case of the
900 * auto-generated linear subgraph, it's a struct containing a
901 * linked list of val_nodes; each param_node->val is duplicated
902 * to each val_node->val. For the last transition function, this
903 * linked list is converted into a parameter array for the key
904 * module. The head val_node is always empty and serves only as
907 * This is the entrance transition function callback. This means that
908 * it is a transition node to the key module selection parameter
909 * node. This means that the parameter node's value indicates the
910 * alias of the key module to which this function applies. That is why
911 * we call ecryptfs_find_key_mod() to get the key module. The exit
912 * transition function is going to need this key module struct so that
913 * it can attach the final parameter value array to it.
916 ecryptfs_enter_linear_subgraph_tf(struct ecryptfs_ctx *ctx,
917 struct param_node *param_node,
918 struct val_node **mnt_params, void **foo)
920 struct ecryptfs_subgraph_ctx *subgraph_ctx;
923 if ((subgraph_ctx = malloc(sizeof(struct ecryptfs_subgraph_ctx)))
928 memset(subgraph_ctx, 0, sizeof(struct ecryptfs_subgraph_ctx));
929 if ((rc = ecryptfs_find_key_mod(&subgraph_ctx->key_mod, ctx,
931 syslog(LOG_ERR, "%s: Cannot find key_mod for param_node with "
932 "val = [%s]\n", __FUNCTION__, param_node->val);
936 (*foo) = (void *)subgraph_ctx;
942 * @foo: Contains a struct with a linked list of val_node
943 * structs. Parameter lists are going to be very short, so
944 * there's no list handling optimization here; we just keep
945 * everything in order.
948 ecryptfs_linear_subgraph_val_tf(struct ecryptfs_ctx *ctx,
949 struct param_node *param_node,
950 struct val_node **mnt_params, void **foo)
952 struct val_node *val_node;
953 struct val_node *walker;
954 struct ecryptfs_subgraph_ctx *subgraph_ctx;
957 if (param_node->val == NULL) {
958 syslog(LOG_WARNING, "No value supplied for parameter node with "
959 "primary opt name [%s]\n", param_node->mnt_opt_names[0]);
962 if ((val_node = malloc(sizeof(struct val_node))) == NULL) {
966 memset(val_node, 0, sizeof(struct val_node));
967 if ((rc = asprintf((char **)&val_node->val, "%s", param_node->val))
974 subgraph_ctx = (struct ecryptfs_subgraph_ctx *)(*foo);
975 walker = &subgraph_ctx->head_val_node;
977 walker = walker->next;
978 walker->next = val_node;
984 * ecryptfs_exit_linear_subgraph_tf
985 * @foo: Linked list of val_node structs.
987 * This is executed when transitioning from the param_node immediately
988 * after the last param_node that deals with a value. The first
989 * element in the list is an empty placeholder and shall always
990 * exist. This function converts the parameter value linked list into
991 * a parameter value array for the module to use.
994 ecryptfs_exit_linear_subgraph_tf(struct ecryptfs_ctx *ctx,
995 struct param_node *param_node,
996 struct val_node **mnt_params, void **foo)
998 struct val_node *curr;
999 uint32_t num_param_vals = 0;
1000 struct key_mod_param_val *param_vals;
1001 struct ecryptfs_subgraph_ctx *subgraph_ctx;
1003 char sig[ECRYPTFS_SIG_SIZE_HEX + 1];
1007 subgraph_ctx = (struct ecryptfs_subgraph_ctx *)(*foo);
1008 curr = subgraph_ctx->head_val_node.next;
1013 subgraph_ctx->key_mod->num_param_vals = num_param_vals;
1014 if (num_param_vals == 0) {
1015 subgraph_ctx->key_mod->param_vals = NULL;
1016 goto out_free_subgraph_ctx;
1018 param_vals = malloc(sizeof(struct key_mod_param_val) * num_param_vals);
1019 if (param_vals == NULL) {
1021 goto out_free_list_and_subgraph_ctx;
1023 curr = subgraph_ctx->head_val_node.next;
1026 if ((rc = asprintf(¶m_vals[i].val, "%s",
1027 (char *)curr->val)) == -1) {
1030 goto out_free_list_and_subgraph_ctx;
1033 param_vals[i].val = NULL;
1037 subgraph_ctx->key_mod->param_vals = param_vals;
1038 if ((rc = ecryptfs_add_key_module_key_to_keyring(
1039 sig, subgraph_ctx->key_mod)) < 0) {
1040 syslog(LOG_ERR, "Error attempting to add key to keyring for "
1041 "key module [%s]; rc = [%d]\n",
1042 subgraph_ctx->key_mod->alias, rc);
1044 goto out_free_list_and_subgraph_ctx;
1046 if ((rc = asprintf(&sig_mnt_opt, "ecryptfs_sig=%s", sig)) == -1) {
1048 goto out_free_list_and_subgraph_ctx;
1050 rc = stack_push(mnt_params, sig_mnt_opt);
1051 out_free_list_and_subgraph_ctx:
1052 curr = subgraph_ctx->head_val_node.next;
1054 struct val_node *next;
1062 out_free_subgraph_ctx:
1069 * ecryptfs_build_linear_subgraph
1070 * @trans_node: This function allocates this new transition node into
1071 * its generated subgraph
1072 * @key_mod: The key module containing the parameter list to use as
1073 * the basis for generating the subgraph
1075 * Generates a subgraph of the decision tree from the set of
1076 * parameters provided by the key module.
1078 * Callbacks manage the conversion of the parameter node subgraph to
1079 * the parameter value array that the module makes use of. The first
1080 * callback initializes the val_node data structure to be an empty
1081 * linked list of values. The subsequent callbacks append the
1082 * parameter node values to the list. The last callback allocates a
1083 * chunk of memory for the parameter values array
1084 * (key_mod->param_vals), transfers the values in the list into that
1085 * array, and frees the list. It then calls
1086 * ecryptfs_add_key_module_key_to_keyring() with this parameter value
1087 * list. This, in turn, calls ecryptfs_generate_key_payload(), which
1088 * calls the module's get_blob() function and takes steps to generate
1089 * the key signature. The exit callback appends an ecryptfs_sig=
1090 * parameter to the mnt_params list.
1092 * A dummy param_node is built by setting the NO_VALUE flag in
1093 * param_node->flags; the transition_node that will be taken by
1094 * default needs to have its value set to the string "default".
1096 * The total number of param_node structs generated is the number of
1097 * parameters plus two. The last two nodes are for (1) providing a
1098 * callback to convert the nvp list to a params array and (2)
1099 * providing a dummy node that can have its own transition set by
1100 * libecryptfs to whatever it wants to set it to.
1102 int ecryptfs_build_linear_subgraph(struct transition_node **trans_node,
1103 struct ecryptfs_key_mod *key_mod)
1105 struct param_node *param_node;
1106 struct transition_node *tmp_tn;
1107 struct key_mod_param *params;
1108 uint32_t num_params;
1112 if ((rc = key_mod->ops->get_params(¶ms, &num_params))) {
1113 syslog(LOG_WARNING, "Key module [%s] returned error whilst "
1114 "retrieving parameter list; rc = [%d]\n",
1115 key_mod->alias, rc);
1118 if ((params == NULL) || (num_params == 0)) {
1119 syslog(LOG_WARNING, "Key module [%s] has empty "
1120 "parameter list\n", key_mod->alias);
1123 if (((*trans_node) = tmp_tn = malloc(sizeof(struct transition_node)))
1128 memset(tmp_tn, 0, sizeof(struct transition_node));
1129 if ((rc = asprintf(&tmp_tn->val, "%s", key_mod->alias)) == -1) {
1133 if ((rc = asprintf(&tmp_tn->pretty_val, "%s", key_mod->alias))
1138 tmp_tn->trans_func = &ecryptfs_enter_linear_subgraph_tf;
1141 for (i = 0; params && i < num_params; i++) {
1142 if ((param_node = malloc(sizeof(struct param_node))) == NULL) {
1146 memset(param_node, 0, sizeof(struct param_node));
1147 if ((rc = asprintf(¶m_node->mnt_opt_names[0], "%s",
1148 params[i].option)) == -1) {
1152 param_node->num_mnt_opt_names = 1;
1153 if (params[i].description) {
1154 if ((rc = asprintf(¶m_node->prompt, "%s",
1155 params[i].description)) == -1) {
1160 if ((rc = asprintf(¶m_node->prompt, "%s",
1161 params[i].option)) == -1) {
1165 if (params[i].default_val)
1166 if ((rc = asprintf(¶m_node->default_val, "%s",
1167 params[i].default_val)) == -1) {
1171 if (params[i].suggested_val)
1172 if ((rc = asprintf(¶m_node->suggested_val, "%s",
1173 params[i].suggested_val)) == -1) {
1178 param_node->val_type = VAL_STR;
1179 ecryptfs_map_flags(¶m_node->flags, params[i].flags);
1180 tmp_tn->next_token = param_node;
1181 tmp_tn = ¶m_node->tl[0];
1182 if ((rc = asprintf(&tmp_tn->val, "default")) == -1) {
1186 tmp_tn->trans_func = &ecryptfs_linear_subgraph_val_tf;
1187 param_node->num_transitions = 1;
1189 if ((param_node = malloc(sizeof(struct param_node))) == NULL) {
1193 memset(param_node, 0, sizeof(struct param_node));
1194 if ((rc = asprintf(¶m_node->mnt_opt_names[0],
1195 "linear_subgraph_exit_dummy_node")) == -1) {
1200 param_node->num_mnt_opt_names = 1;
1201 param_node->flags |= ECRYPTFS_PARAM_FLAG_NO_VALUE;
1202 tmp_tn->next_token = param_node;
1203 tmp_tn = ¶m_node->tl[0];
1204 if ((rc = asprintf(&tmp_tn->val, "default")) == -1) {
1209 param_node->num_transitions = 1;
1210 tmp_tn->trans_func = &ecryptfs_exit_linear_subgraph_tf;