PromiseResult VerifyAbsoluteLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp) { char absto[CF_BUFSIZE]; char expand[CF_BUFSIZE]; char linkto[CF_BUFSIZE]; if (*source == '.') { strcpy(linkto, destination); ChopLastNode(linkto); AddSlash(linkto); strcat(linkto, source); } else { strcpy(linkto, source); } CompressPath(absto, linkto); expand[0] = '\0'; if (attr.link.when_no_file == cfa_force) { if (!ExpandLinks(expand, absto, 0)) /* begin at level 1 and beam out at 15 */ { Log(LOG_LEVEL_ERR, "Failed to make absolute link in"); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_FAIL; } else { Log(LOG_LEVEL_DEBUG, "ExpandLinks returned '%s'", expand); } } else { strcpy(expand, absto); } CompressPath(linkto, expand); return VerifyLink(ctx, destination, linkto, attr, pp); }
int AbsoluteLink(char *from, char *to, struct Item *inclusions, struct Item *exclusions, struct Item *copy, short nofile, struct Link *ptr) { char absto[CF_BUFSIZE]; char expand[CF_BUFSIZE]; Debug2("AbsoluteLink(%s,%s)\n",from,to); if (*to == '.') { strcpy(g_linkto,from); ChopLastNode(g_linkto); AddSlash(g_linkto); strcat(g_linkto,to); } else { strcpy(g_linkto,to); } CompressPath(absto,g_linkto); expand[0] = '\0'; if (!nofile) { /* begin at level 1 and beam out at 15 */ if (!ExpandLinks(expand,absto,0)) { CfLog(cferror,"Failed to make absolute link in\n",""); snprintf(g_output,CF_BUFSIZE*2,"%s -> %s\n",from,to); CfLog(cferror,g_output,""); return false; } else { Debug2("ExpandLinks returned %s\n",expand); } } else { strcpy(expand,absto); } CompressPath(g_linkto,expand); return LinkFiles(from,g_linkto,inclusions,exclusions,copy,nofile,ptr); }
int ExpandLinks(char *dest, const char *from, int level) { char buff[CF_BUFSIZE]; char node[CF_MAXLINKSIZE]; struct stat statbuf; int lastnode = false; memset(dest, 0, CF_BUFSIZE); if (level >= CF_MAXLINKLEVEL) { Log(LOG_LEVEL_ERR, "Too many levels of symbolic links to evaluate absolute path"); return false; } const char *sp = from; while (*sp != '\0') { if (*sp == FILE_SEPARATOR) { sp++; continue; } sscanf(sp, "%[^/]", node); sp += strlen(node); if (*sp == '\0') { lastnode = true; } if (strcmp(node, ".") == 0) { continue; } if (strcmp(node, "..") == 0) { continue; } else { strcat(dest, "/"); } strcat(dest, node); if (lstat(dest, &statbuf) == -1) /* File doesn't exist so we can stop here */ { Log(LOG_LEVEL_ERR, "Can't stat '%s' in ExpandLinks. (lstat: %s)", dest, GetErrorStr()); return false; } if (S_ISLNK(statbuf.st_mode)) { memset(buff, 0, CF_BUFSIZE); if (readlink(dest, buff, CF_BUFSIZE - 1) == -1) { Log(LOG_LEVEL_ERR, "Expand links can't stat '%s'. (readlink: %s)", dest, GetErrorStr()); return false; } else { if (buff[0] == '.') { ChopLastNode(dest); AddSlash(dest); if (!JoinPath(dest, buff)) { return false; } } else if (IsAbsoluteFileName(buff)) { strcpy(dest, buff); DeleteSlash(dest); if (strcmp(dest, from) == 0) { Log(LOG_LEVEL_DEBUG, "No links to be expanded"); return true; } if ((!lastnode) && (!ExpandLinks(buff, dest, level + 1))) { return false; } } else { ChopLastNode(dest); AddSlash(dest); strcat(dest, buff); DeleteSlash(dest); if (strcmp(dest, from) == 0) { Log(LOG_LEVEL_DEBUG, "No links to be expanded"); return true; } memset(buff, 0, CF_BUFSIZE); if ((!lastnode) && (!ExpandLinks(buff, dest, level + 1))) { return false; } } } } } return true; }
int ExpandLinks(char *dest, char *from, int level) { char *sp, buff[CF_BUFSIZE]; char node[CF_MAXLINKSIZE]; struct stat statbuf; int lastnode = false; memset(dest,0,CF_BUFSIZE); Debug2("ExpandLinks(%s,%d)\n",from,level); if (level >= CF_MAXLINKLEVEL) { CfLog(cferror, "Too many levels of symbolic links to evaluate " "absolute path\n",""); return false; } for (sp = from; *sp != '\0'; sp++) { if (*sp == '/') { continue; } sscanf(sp,"%[^/]",node); sp += strlen(node); if (*sp == '\0') { lastnode = true; } if (strcmp(node,".") == 0) { continue; } if (strcmp(node,"..") == 0) { if (! ChopLastNode(g_linkto)) { Debug("cfagent: used .. beyond top of filesystem!\n"); return false; } continue; } else { strcat(dest,"/"); } strcat(dest,node); /* File doesn't exist so we can stop here */ if (lstat(dest,&statbuf) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Can't stat %s in ExpandLinks\n", dest); CfLog(cferror,g_output,"stat"); return false; } if (S_ISLNK(statbuf.st_mode)) { memset(buff,0,CF_BUFSIZE); if (readlink(dest,buff,CF_BUFSIZE-1) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Expand links can't stat %s\n", dest); CfLog(cferror,g_output,"readlink"); return false; } else { if (buff[0] == '.') { ChopLastNode(dest); AddSlash(dest); if (BufferOverflow(dest,buff)) { return false; } strcat(dest,buff); } else if (buff[0] == '/') { strcpy(dest,buff); DeleteSlash(dest); if (strcmp(dest,from) == 0) { Debug2("No links to be expanded\n"); return true; } if (!lastnode && !ExpandLinks(buff,dest,level+1)) { return false; } } else { ChopLastNode(dest); AddSlash(dest); strcat(dest,buff); DeleteSlash(dest); if (strcmp(dest,from) == 0) { Debug2("No links to be expanded\n"); return true; } memset(buff,0,CF_BUFSIZE); if (!lastnode && !ExpandLinks(buff,dest,level+1)) { return false; } } } } } return true; }