Beispiel #1
0
FileRecord *Dir_resolve_file(Dir *dir, bstring path)
{
    FileRecord *file = NULL;
    bstring target = NULL;

    check(Dir_lazy_normalize_base(dir) == 0, "Failed to normalize base path when requesting %s",
            bdata(path));

    check(bstrncmp(path, dir->prefix, blength(dir->prefix)) == 0, 
            "Request for path %s does not start with %s prefix.", 
            bdata(path), bdata(dir->prefix));

    file = FileRecord_cache_check(dir, path);

    if(file) {
        // TODO: double check this gives the right users count
        file->users++;
        return file;
    }

    // We subtract one from the blengths below, because dir->prefix includes
    // a trailing '/'.  If we skip over this in path->data, we drop the '/'
    // from the URI, breaking the target path
    if(bchar(path, blength(path) - 1) == '/') {
        target = bformat("%s%s%s",
                    bdata(dir->normalized_base),
                    path->data + blength(dir->prefix) - 1,
                    bdata(dir->index_file));
    } else {
        target = bformat("%s%s",
                bdata(dir->normalized_base),
                path->data + blength(dir->prefix) - 1);
    }

    check(target, "Couldn't construct target path for %s", bdata(path));

    check_debug(normalize_path(target) == 0, "Failed to normalize target path.");
   
    check_debug(bstrncmp(target, dir->normalized_base, blength(dir->normalized_base)) == 0, 
            "Request for path %s does not start with %s base after normalizing.", 
            bdata(target), bdata(dir->base));

    // the FileRecord now owns the target
    file = Dir_find_file(target, dir->default_ctype);
    check_debug(file, "Error opening file: %s", bdata(target));

    // Increment the user count because we're adding it to the cache
    file->users++;
    file->request_path = bstrcpy(path);
    Cache_add(dir->fr_cache, file);


    return file;

error:
    bdestroy(target);
    FileRecord_release(file);
    return NULL;
}
Beispiel #2
0
/*
 * See in the tree with selected files what files were selected to be restored.
 */
static inline int set_files_to_restore(JCR *jcr, struct ndm_job_param *job, int32_t FileIndex,
                                       const char *restore_prefix, const char *ndmp_filesystem)
{
   int len;
   int cnt = 0;
   TREE_NODE *node, *parent;
   POOL_MEM restore_pathname, tmp;

   node = first_tree_node(jcr->restore_tree_root);
   while (node) {
      /*
       * See if this is the wanted FileIndex and the user asked to extract it.
       */
      if (node->FileIndex == FileIndex && node->extract) {
         pm_strcpy(restore_pathname, node->fname);

         /*
          * Walk up the parent until we hit the head of the list.
          */
         for (parent = node->parent; parent; parent = parent->parent) {
            pm_strcpy(tmp, restore_pathname.c_str());
            Mmsg(restore_pathname, "%s/%s", parent->fname, tmp.c_str());
         }

         /*
          * We only want to restore the non pseudo NDMP names e.g. not the full backup stream name.
          */
         if (!bstrncmp(restore_pathname.c_str(), "/@NDMP/", 7)) {
            /*
             * See if we need to strip the prefix from the filename.
             */
            len = strlen(ndmp_filesystem);
            if (bstrncmp(restore_pathname.c_str(), ndmp_filesystem, len)) {
               add_to_namelist(job,  restore_pathname.c_str() + len, restore_prefix,
                               (char *)"", (char *)"", NDMP_INVALID_U_QUAD);
            } else {
               add_to_namelist(job,  restore_pathname.c_str(), restore_prefix,
                               (char *)"", (char *)"", NDMP_INVALID_U_QUAD);
            }
            cnt++;
         }
      }

      node = next_tree_node(node);
   }

   return cnt;
}
Beispiel #3
0
/*
 * Check if this is a cleaning tape by comparing the Volume name
 *  with the Cleaning Prefix. If they match, this is a cleaning
 *  tape.
 */
static inline bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
{
   bool retval;

   /*
    * Find Pool resource
    */
   ua->jcr->res.pool = (POOLRES *)GetResWithName(R_POOL, pr->Name);
   if (!ua->jcr->res.pool) {
      ua->error_msg(_("Pool \"%s\" resource not found for volume \"%s\"!\n"),
                    pr->Name, mr->VolumeName);
      return false;
   }

   retval = bstrncmp(mr->VolumeName,
                     ua->jcr->res.pool->cleaning_prefix,
                     strlen(ua->jcr->res.pool->cleaning_prefix));

   Dmsg4(100, "CLNprefix=%s: Vol=%s: len=%d bstrncmp=%s\n",
         ua->jcr->res.pool->cleaning_prefix, mr->VolumeName,
         strlen(ua->jcr->res.pool->cleaning_prefix),
         retval ? "true" : "false");

   return retval;
}
Beispiel #4
0
/*
 * Walk the tree of selected files for restore and lookup the
 * correct fileid. Return the actual full pathname of the file
 * corresponding to the given fileid.
 */
static inline char *lookup_fileindex(JCR *jcr, int32_t FileIndex)
{
   TREE_NODE *node, *parent;
   POOL_MEM restore_pathname, tmp;

   node = first_tree_node(jcr->restore_tree_root);
   while (node) {
      /*
       * See if this is the wanted FileIndex.
       */
      if (node->FileIndex == FileIndex) {
         pm_strcpy(restore_pathname, node->fname);

         /*
          * Walk up the parent until we hit the head of the list.
          */
         for (parent = node->parent; parent; parent = parent->parent) {
            pm_strcpy(tmp, restore_pathname.c_str());
            Mmsg(restore_pathname, "%s/%s", parent->fname, tmp.c_str());
         }

         if (bstrncmp(restore_pathname.c_str(), "/@NDMP/", 7)) {
            return bstrdup(restore_pathname.c_str());
         }
      }

      node = next_tree_node(node);
   }

   return NULL;
}
Beispiel #5
0
/*
 * Search the table of built-in variables, and if found,
 * call the appropriate subroutine to do the work.
 */
static var_rc_t lookup_built_in_var(var_t *ctx,
                                    void *my_ctx,
                                    const char *var_ptr,
                                    int var_len,
                                    int var_index,
                                    const char **val_ptr,
                                    int *val_len,
                                    int *val_size)
{
    JCR *jcr = (JCR *)my_ctx;
    int status, i;

    for (i = 0; _(built_in_vars[i].var_name); i++) {
        if (bstrncmp(_(built_in_vars[i].var_name), var_ptr, var_len)) {
            status = (*built_in_vars[i].func)(jcr, built_in_vars[i].code,
                                              val_ptr, val_len, val_size);
            if (status) {
                return VAR_OK;
            }
            break;
        }
    }

    return VAR_ERR_UNDEFINED_VARIABLE;
}
Beispiel #6
0
static s32 binaryFind(LTable* lt, const char* hash)
{
        u32 start = 0;
        u32 end   = lt->n_rows-1;
        while (start != end)
        {
                u32 middle = (start + end) / 2;
                if (bstrncmp(hash, CHASH(middle), lt->l_hash) <= 0)
                        end = middle;
                else
                        start = middle + 1;
        }
        if (bstrncmp(CHASH(start), hash, lt->l_hash) == 0)
                return start;
        else
                return -1;
}
Beispiel #7
0
static int
parse_bind_address(allium_ptcfg *cfg, const char *addrs)
{
	struct bstrList *l;
	struct tagbstring str;
	int i, j;

	assert(NULL != cfg);

	if (NULL == addrs) {
		fprintf(stdout, "ENV-ERROR No Bind Addresses\n");
		return (-1);
	}
	btfromcstr(str, addrs);
	if (0 == btlength(str)) {
		fprintf(stdout, "ENV-ERROR Empty Bind Address\n");
		return (-1);
	}
	l = bsplit(&str, ',');
	if (NULL == l) {
		fprintf(stdout, "ENV-ERROR OOM parsing Bind Addresses\n");
		return (-1);
	}
	if (l->qty != cfg->nr_methods) {
		fprintf(stdout, "ENV-ERROR Malformed Bind Addresses\n");
		bstrListDestroy(l);
		return (-1);
	}
	for (i = 0; i < l->qty; i++) {
		/*
		 * Per pt-spec.txt, the order is identical to the transport
		 * list.  I have no idea what is supposed to happen when
		 * the transport list is wildcarded, so this routine will
		 * currently fail gracefully.
		 */
		j = bstrrchr(l->entry[i], '-');
		if ((j != blength(cfg->methods[i].name)) || bstrncmp(l->entry[i],
			    cfg->methods[i].name, j - 1)) {
			fprintf(stdout, "ENV-ERROR Unexpected method in Bind Address\n");
			bstrListDestroy(l);
			return (-1);
		}
		cfg->methods[i].bind_addr_len = sizeof(cfg->methods[i].bind_addr);
		if (parse_addr(bdataofs(l->entry[i], j + 1),
			    (struct sockaddr *)&cfg->methods[i].bind_addr,
			    &cfg->methods[i].bind_addr_len)) {
			fprintf(stdout, "ENV-ERROR Invalid address in Bind Address (%s)\n",
			    bdata(l->entry[i]));
			bstrListDestroy(l);
			return (-1);
		}
		cfg->methods[i].has_bind_addr = 1;
	}
	bstrListDestroy(l);

	return (0);
}
Beispiel #8
0
/*
 * Authenticate Director
 */
bool BSOCK::authenticate_with_director(JCR *jcr,
                                       const char *name, s_password &password, tls_t &tls,
                                       char *response, int response_len)
{
   char bashed_name[MAX_NAME_LENGTH];
   BSOCK *dir = this;        /* for readability */

   response[0] = 0;

   /*
    * Send my name to the Director then do authentication
    */
   bstrncpy(bashed_name, name, sizeof(bashed_name));
   bash_spaces(bashed_name);

   /*
    * Timeout Hello after 5 mins
    */
   dir->start_timer(60 * 5);
   dir->fsend(hello, bashed_name);

   if (!authenticate_outbound_connection(jcr, "Director", name, password, tls)) {
      goto bail_out;
   }

   Dmsg1(6, ">dird: %s", dir->msg);
   if (dir->recv() <= 0) {
      dir->stop_timer();
      bsnprintf(response, response_len, _("Bad response to Hello command: ERR=%s\n"
                                          "The Director at \"%s:%d\" is probably not running.\n"),
                dir->bstrerror(), dir->host(), dir->port());
      return false;
   }

   dir->stop_timer();
   Dmsg1(10, "<dird: %s", dir->msg);
   if (!bstrncmp(dir->msg, OKhello, sizeof(OKhello) - 1)) {
      bsnprintf(response, response_len, _("Director at \"%s:%d\" rejected Hello command\n"),
                dir->host(), dir->port());
      return false;
   } else {
      bsnprintf(response, response_len, "%s", dir->msg);
   }

   return true;

bail_out:
   dir->stop_timer();
   bsnprintf(response, response_len, _("Authorization problem with Director at \"%s:%d\"\n"
                                       "Most likely the passwords do not agree.\n"
                                       "If you are using TLS, there may have been a certificate "
                                       "validation error during the TLS handshake.\n"
                                       "Please see %s for help.\n"),
             dir->host(), dir->port(), MANUAL_AUTH_URL);

   return false;
}
Beispiel #9
0
/*
 * Now talk to the SD and do what he says
 */
static void do_sd_commands(JCR *jcr)
{
   int i, status;
   bool found, quit;
   BSOCK *sd = jcr->store_bsock;

   sd->set_jcr(jcr);
   quit = false;
   while (!quit) {
      /*
       * Read command coming from the Storage daemon
       */
      status = sd->recv();
      if (is_bnet_stop(sd)) {         /* hardeof or error */
         break;                       /* connection terminated */
      }
      if (status <= 0) {
         continue;                    /* ignore signals and zero length msgs */
      }

      Dmsg1(110, "<stored: %s", sd->msg);
      found = false;
      for (i = 0; sd_cmds[i].cmd; i++) {
         if (bstrncmp(sd_cmds[i].cmd, sd->msg, strlen(sd_cmds[i].cmd))) {
            found = true;               /* indicate command found */
            jcr->errmsg[0] = 0;
            if (!sd_cmds[i].func(jcr)) {    /* do command */
               /*
                * Note sd->msg command may be destroyed by comm activity
                */
               if (!job_canceled(jcr)) {
                  if (jcr->errmsg[0]) {
                     Jmsg1(jcr, M_FATAL, 0, _("Command error with SD, hanging up. %s\n"),
                           jcr->errmsg);
                  } else {
                     Jmsg0(jcr, M_FATAL, 0, _("Command error with SD, hanging up.\n"));
                  }
                  jcr->setJobStatus(JS_ErrorTerminated);
               }
               quit = true;
            }
            break;
         }
      }

      if (!found) {                   /* command not found */
         if (!job_canceled(jcr)) {
            Jmsg1(jcr, M_FATAL, 0, _("SD command not found: %s\n"), sd->msg);
            Dmsg1(110, "<stored: Command not found: %s\n", sd->msg);
         }
         sd->fsend(serrmsg);
         break;
      }
   }
   sd->signal(BNET_TERMINATE);        /* signal to SD job is done */
}
Beispiel #10
0
/*
 * Now talk to the FD and do what he says
 */
void do_fd_commands(JCR *jcr)
{
   int i;
   bool found, quit;
   BSOCK *fd = jcr->file_bsock;

   fd->set_jcr(jcr);
   for (quit=false; !quit;) {
      int status;

      /* Read command coming from the File daemon */
      status = fd->recv();
      if (is_bnet_stop(fd)) {         /* hardeof or error */
         break;                       /* connection terminated */
      }
      if (status <= 0) {
         continue;                    /* ignore signals and zero length msgs */
      }
      Dmsg1(110, "<filed: %s", fd->msg);
      found = false;
      for (i=0; fd_cmds[i].cmd; i++) {
         if (bstrncmp(fd_cmds[i].cmd, fd->msg, strlen(fd_cmds[i].cmd))) {
            found = true;               /* indicate command found */
            jcr->errmsg[0] = 0;
            if (!fd_cmds[i].func(jcr)) {    /* do command */
               /* Note fd->msg command may be destroyed by comm activity */
               if (!job_canceled(jcr)) {
                  if (jcr->errmsg[0]) {
                     Jmsg1(jcr, M_FATAL, 0, _("Command error with FD, hanging up. %s\n"),
                           jcr->errmsg);
                  } else {
                     Jmsg0(jcr, M_FATAL, 0, _("Command error with FD, hanging up.\n"));
                  }
                  jcr->setJobStatus(JS_ErrorTerminated);
               }
               quit = true;
            }
            break;
         }
      }
      if (!found) {                   /* command not found */
         if (!job_canceled(jcr)) {
            Jmsg1(jcr, M_FATAL, 0, _("FD command not found: %s\n"), fd->msg);
            Dmsg1(110, "<filed: Command not found: %s\n", fd->msg);
         }
         fd->fsend(ferrmsg);
         break;
      }
   }
   fd->signal(BNET_TERMINATE);        /* signal to FD job is done */
}
Beispiel #11
0
/*
 * Called here to do a special operation on a variable
 *   op_ptr  points to the special operation code (not EOS terminated)
 *   arg_ptr points to argument to special op code
 *   val_ptr points to the value string
 *   out_ptr points to string to be returned
 */
static var_rc_t operate_var(var_t *var,
                            void *my_ctx,
                            const char *op_ptr,
                            int op_len,
                            const char *arg_ptr,
                            int arg_len,
                            const char *val_ptr,
                            int val_len,
                            char **out_ptr,
                            int *out_len,
                            int *out_size)
{
    COUNTERRES *counter;
    POOL_MEM buf(PM_NAME);
    var_rc_t status = VAR_ERR_UNDEFINED_OPERATION;

    Dmsg0(100, "Enter operate_var\n");
    if (!val_ptr) {
        *out_size = 0;
        return status;
    }

    if (op_len == 3 && bstrncmp(op_ptr, "inc", 3)) {
        buf.check_size(val_len + 1);
        pm_memcpy(buf, arg_ptr, val_len);
        (buf.c_str())[val_len] = 0;
        Dmsg1(100, "Arg=%s\n", buf.c_str());

        pm_memcpy(buf, val_ptr, val_len);
        (buf.c_str())[val_len] = 0;
        Dmsg1(100, "Val=%s\n", buf.c_str());

        LockRes();
        for (counter = NULL; (counter = (COUNTERRES *)GetNextRes(R_COUNTER, (RES *)counter)); ) {
            if (bstrcmp(counter->name(), buf.c_str())) {
                Dmsg2(100, "counter=%s val=%s\n", counter->name(), buf.c_str());
                break;
            }
        }
        UnlockRes();
        return status;
    }
    *out_size = 0;

    return status;
}
Beispiel #12
0
static void quicksort(LTable* lt, u32 left, u32 right)
{
	if (left >= right)
		return;

	swap(lt, (left+right)/2, right);
	char* pivotValue = CHASH(right);
	u32 storeIndex = left;
	for (u32 i = left; i < right; i++)
		if (bstrncmp(CHASH(i), pivotValue, lt->l_hash) < 0)
			swap(lt, i, storeIndex++);

	swap(lt, storeIndex, right);

	if (storeIndex)
		quicksort(lt, left, storeIndex-1);
	quicksort(lt, storeIndex+1, right);
}
Beispiel #13
0
Datei: tree.c Projekt: AlD/bareos
/*
 * Do a relative cwd -- i.e. relative to current node rather than root node
 */
TREE_NODE *tree_relcwd(char *path, TREE_ROOT *root, TREE_NODE *node)
{
   char *p;
   int len;
   TREE_NODE *cd;
   char save_char;
   int match;

   if (*path == 0) {
      return node;
   }

   /*
    * Check the current segment only
    */
   if ((p = first_path_separator(path)) != NULL) {
      len = p - path;
   } else {
      len = strlen(path);
   }

   Dmsg2(100, "tree_relcwd: len=%d path=%s\n", len, path);

   foreach_child(cd, node) {
      Dmsg1(100, "tree_relcwd: test cd=%s\n", cd->fname);
      if (cd->fname[0] == path[0] && len == (int)strlen(cd->fname)
          && bstrncmp(cd->fname, path, len)) {
         break;
      }

      /*
       * fnmatch has no len in call so we truncate the string
       */
      save_char = path[len];
      path[len] = 0;
      match = fnmatch(path, cd->fname, 0) == 0;
      path[len] = save_char;

      if (match) {
         break;
      }
   }
Beispiel #14
0
/*
 * Given a Job, find the JCR compares on the number of
 * characters in Job thus allowing partial matches.
 *
 * Returns: jcr on success
 *          NULL on failure
 */
JCR *get_jcr_by_partial_name(char *Job)
{
    JCR *jcr;
    int len;

    if (!Job) {
        return NULL;
    }
    len = strlen(Job);
    foreach_jcr(jcr) {
        if (bstrncmp(Job, jcr->Job, len)) {
            jcr->inc_use_count();
            Dmsg3(dbglvl, "Inc get_jcr jid=%u use_count=%d Job=%s\n",
                  jcr->JobId, jcr->use_count(), jcr->Job);
            break;
        }
    }
    endeach_jcr(jcr);
    return jcr;
}
Beispiel #15
0
/* Generator function for command completion.  STATE lets us know whether
 * to start from scratch; without any state (i.e. STATE == 0), then we
 * start at the top of the list.
 */
static char *item_generator(const char *text, int state,
                            const char *item, cpl_item_t type)
{
  static int list_index, len;
  char *name;

  /* If this is a new word to complete, initialize now.  This includes
   * saving the length of TEXT for efficiency, and initializing the index
   *  variable to 0.
   */
  if (!state)
  {
     list_index = 0;
     len = strlen(text);
     switch(type) {
     case ITEM_ARG:
        get_items(item);
        break;
     case ITEM_HELP:
        get_arguments(item);
        break;
     }
  }

  /* Return the next name which partially matches from the command list. */
  while (items && list_index < items->list.size())
  {
     name = (char *)items->list[list_index];
     list_index++;

     if (bstrncmp(name, text, len)) {
        char *ret = (char *) actuallymalloc(strlen(name)+1);
        strcpy(ret, name);
        return ret;
     }
  }

  /* If no names matched, then return NULL. */
  return ((char *)NULL);
}
Beispiel #16
0
/*
 * Store a password at specified address in MD5 coding
 */
static void store_md5password(LEX *lc, RES_ITEM *item, int index, int pass)
{
   s_password *pwd;
   URES *res_all = (URES *)my_config->m_res_all;

   lex_get_token(lc, T_STRING);
   if (pass == 1) {
      pwd = item->pwdvalue;

      if (pwd->value) {
         free(pwd->value);
      }

      /*
       * See if we are parsing an MD5 encoded password already.
       */
      if (bstrncmp(lc->str, "[md5]", 5)) {
         pwd->encoding = p_encoding_md5;
         pwd->value = bstrdup(lc->str + 5);
      } else {
         unsigned int i, j;
         struct MD5Context md5c;
         unsigned char digest[CRYPTO_DIGEST_MD5_SIZE];
         char sig[100];

         MD5Init(&md5c);
         MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len);
         MD5Final(digest, &md5c);
         for (i = j = 0; i < sizeof(digest); i++) {
            sprintf(&sig[j], "%02x", digest[i]);
            j += 2;
         }
         pwd->encoding = p_encoding_md5;
         pwd->value = bstrdup(sig);
      }
   }
   scan_to_eol(lc);
   set_bit(index, res_all->hdr.item_present);
}
Beispiel #17
0
/*
 * Check if a certain fileset include pattern shadows another pattern.
 */
static inline bool check_include_pattern_shadowing(JCR *jcr,
                                                   const char *pattern1,
                                                   const char *pattern2,
                                                   bool recursive)
{
   int len1, len2;
   bool retval = false;
   struct stat st1, st2;

   /*
    * See if one directory shadows the other or if two
    * files are hardlinked.
    */
   if (lstat(pattern1, &st1) != 0) {
      berrno be;
      Jmsg(jcr, M_WARNING, 0,
           _("Cannot stat file %s: ERR=%s\n"),
           pattern1, be.bstrerror());
      goto bail_out;
   }

   if (lstat(pattern2, &st2) != 0) {
      berrno be;
      Jmsg(jcr, M_WARNING, 0,
           _("Cannot stat file %s: ERR=%s\n"),
           pattern2, be.bstrerror());
      goto bail_out;
   }

   if (S_ISDIR(st1.st_mode) && S_ISDIR(st2.st_mode)) {
      /*
       * Only check shadowing of directories when recursion is turned on.
       */
      if (recursive ) {
         len1 = strlen(pattern1);
         len2 = strlen(pattern2);

         /*
          * See if one pattern shadows the other.
          */
         if (((len1 < len2 && pattern1[len1] == '\0' && IsPathSeparator(pattern2[len1])) ||
              (len1 > len2 && IsPathSeparator(pattern1[len2]) && pattern1[len1] == '\0')) &&
             bstrncmp(pattern1, pattern2, MIN(len1, len2))) {
            /*
             * If both directories have the same st_dev they shadow
             * each other e.g. are not on seperate filesystems.
             */
            if (st1.st_dev == st2.st_dev) {
               retval = true;
            }
         }
      }
   } else {
      /*
       * See if the two files are hardlinked.
       */
      if (st1.st_dev == st2.st_dev &&
          st1.st_ino == st2.st_ino) {
         retval = true;
      }
   }

bail_out:
   return retval;
}
Beispiel #18
0
FileRecord *Dir_resolve_file(Dir *dir, bstring pattern, bstring path)
{
    FileRecord *file = NULL;
    bstring target = NULL;
    bstring prefix = NULL;

    check(Dir_lazy_normalize_base(dir) == 0, "Failed to normalize base path when requesting %s",
            bdata(path));

    file = FileRecord_cache_check(dir, path);

    if(file) {
        // TODO: double check this gives the right users count
        file->users++;
        return file;
    }
    
    int paren = bstrchr(pattern, '(');
    prefix = (paren > 0) ? bHead(pattern, paren) : bstrcpy(pattern);

    check(bchar(prefix, 0) == '/', "Route '%s' pointing to directory must have pattern with leading '/'", bdata(pattern));
    check(blength(prefix) < MAX_DIR_PATH, "Prefix is too long, must be less than %d", MAX_DIR_PATH);

    debug("Building target from base: %s pattern: %s prefix: %s path: %s index_file: %s", 
            bdata(dir->normalized_base),
            bdata(pattern),
            bdata(prefix),
            bdata(path),
            bdata(dir->index_file));

    if(bchar(path, blength(path) - 1) == '/') {
        // a directory so figureo out the index file
        target = bformat("%s%s%s",
                         bdata(dir->normalized_base),
                         path->data + blength(prefix) - 1,
                         bdata(dir->index_file));
    } else if(biseq(prefix, path)) {
        target = bformat("%s%s", bdata(dir->normalized_base), bdata(path));

    } else {
        target = bformat("%s%s", bdata(dir->normalized_base), path->data + blength(prefix) - 1);
    }

    check(target, "Couldn't construct target path for %s", bdata(path));

    check_debug(normalize_path(target) == 0,
            "Failed to normalize target path: %s", bdata(target));
   
    check_debug(bstrncmp(target, dir->normalized_base, blength(dir->normalized_base)) == 0, 
            "Request for path %s does not start with %s base after normalizing.", 
            bdata(target), bdata(dir->base));

    // the FileRecord now owns the target
    file = Dir_find_file(target, dir->default_ctype);
    check_debug(file, "Error opening file: %s", bdata(target));

    // Increment the user count because we're adding it to the cache
    file->users++;
    file->request_path = bstrcpy(path);
    Cache_add(dir->fr_cache, file);


    return file;

error:
    bdestroy(target);
    FileRecord_release(file);
    return NULL;
}
Beispiel #19
0
/*
 * Setup device, jcr, and prepare to access device.
 *   If the caller wants read access, acquire the device, otherwise,
 *     the caller will do it.
 */
static DCR *setup_to_access_device(JCR *jcr, char *dev_name,
              const char *VolumeName, int mode)
{
   DEVICE *dev;
   char *p;
   DEVRES *device;
   DCR *dcr;
   char VolName[MAX_NAME_LENGTH];

   init_reservations_lock();

   /*
    * If no volume name already given and no bsr, and it is a file,
    * try getting name from Filename
    */
   if (VolumeName) {
      bstrncpy(VolName, VolumeName, sizeof(VolName));
      if (strlen(VolumeName) >= MAX_NAME_LENGTH) {
         Jmsg0(jcr, M_ERROR, 0, _("Volume name or names is too long. Please use a .bsr file.\n"));
      }
   } else {
      VolName[0] = 0;
   }
   if (!jcr->bsr && VolName[0] == 0) {
      if (!bstrncmp(dev_name, "/dev/", 5)) {
         /* Try stripping file part */
         p = dev_name + strlen(dev_name);

         while (p >= dev_name && !IsPathSeparator(*p))
            p--;
         if (IsPathSeparator(*p)) {
            bstrncpy(VolName, p+1, sizeof(VolName));
            *p = 0;
         }
      }
   }

   if ((device=find_device_res(dev_name, mode)) == NULL) {
      Jmsg2(jcr, M_FATAL, 0, _("Cannot find device \"%s\" in config file %s.\n"),
           dev_name, configfile);
      return NULL;
   }

   dev = init_dev(jcr, device);
   if (!dev) {
      Jmsg1(jcr, M_FATAL, 0, _("Cannot init device %s\n"), dev_name);
      return NULL;
   }
   device->dev = dev;
   jcr->dcr = dcr = new_dcr(jcr, NULL, dev);
   if (VolName[0]) {
      bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
   }
   bstrncpy(dcr->dev_name, device->device_name, sizeof(dcr->dev_name));

   create_restore_volume_list(jcr);

   if (mode) {                        /* read only access? */
      Dmsg0(100, "Acquire device for read\n");
      if (!acquire_device_for_read(dcr)) {
         return NULL;
      }
      jcr->read_dcr = dcr;
   } else {
      if (!first_open_device(dcr)) {
         Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
         return NULL;
      }
      jcr->dcr = dcr;        /* write dcr */
   }
   return dcr;
}
Beispiel #20
0
/*
 * Authenticate Storage daemon connection
 */
bool authenticate_storage_daemon(JCR *jcr, STORERES *store)
{
   BSOCK *sd = jcr->store_bsock;
   char dirname[MAX_NAME_LENGTH];
   int tls_local_need = BNET_TLS_NONE;
   int tls_remote_need = BNET_TLS_NONE;
   int compatible = true;
   bool auth_success = false;

   /*
    * Send my name to the Storage daemon then do authentication
    */
   bstrncpy(dirname, director->hdr.name, sizeof(dirname));
   bash_spaces(dirname);
   /* Timeout Hello after 1 min */
   btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
   if (!sd->fsend(hello, dirname)) {
      stop_bsock_timer(tid);
      Dmsg1(dbglvl, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
      Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
      return 0;
   }

   /* TLS Requirement */
   if (store->tls_enable) {
     if (store->tls_require) {
        tls_local_need = BNET_TLS_REQUIRED;
     } else {
        tls_local_need = BNET_TLS_OK;
     }
   }

   if (store->tls_authenticate) {
      tls_local_need = BNET_TLS_REQUIRED;
   }

   auth_success = cram_md5_respond(sd, store->password, &tls_remote_need, &compatible);
   if (auth_success) {
      auth_success = cram_md5_challenge(sd, store->password, tls_local_need, compatible);
      if (!auth_success) {
         Dmsg1(dbglvl, "cram_challenge failed for %s\n", sd->who());
      }
   } else {
      Dmsg1(dbglvl, "cram_respond failed for %s\n", sd->who());
   }

   if (!auth_success) {
      stop_bsock_timer(tid);
      Dmsg0(dbglvl, _("Director and Storage daemon passwords or names not the same.\n"));
      Jmsg2(jcr, M_FATAL, 0,
            _("Director unable to authenticate with Storage daemon at \"%s:%d\". Possible causes:\n"
            "Passwords or names not the same or\n"
            "Maximum Concurrent Jobs exceeded on the SD or\n"
            "SD networking messed up (restart daemon).\n"
            "Please see " MANUAL_AUTH_URL " for help.\n"),
            sd->host(), sd->port());
      return 0;
   }

   /* Verify that the remote host is willing to meet our TLS requirements */
   if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
      stop_bsock_timer(tid);
      Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not advertise required TLS support.\n"));
      return 0;
   }

   /* Verify that we are willing to meet the remote host's requirements */
   if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
      stop_bsock_timer(tid);
      Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
      return 0;
   }

   /* Is TLS Enabled? */
   if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
      /* Engage TLS! Full Speed Ahead! */
      if (!bnet_tls_client(store->tls_ctx, sd, NULL)) {
         stop_bsock_timer(tid);
         Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with SD at \"%s:%d\"\n"),
            sd->host(), sd->port());
         return 0;
      }
      if (store->tls_authenticate) {       /* authentication only? */
         sd->free_tls();                   /* yes, stop tls */
      }
   }

   Dmsg1(116, ">stored: %s", sd->msg);
   if (sd->recv() <= 0) {
      stop_bsock_timer(tid);
      Jmsg3(jcr, M_FATAL, 0, _("bdird<stored: \"%s:%s\" bad response to Hello command: ERR=%s\n"),
         sd->who(), sd->host(), sd->bstrerror());
      return 0;
   }
   Dmsg1(110, "<stored: %s", sd->msg);
   stop_bsock_timer(tid);
   if (!bstrncmp(sd->msg, OKhello, sizeof(OKhello))) {
      Dmsg0(dbglvl, _("Storage daemon rejected Hello command\n"));
      Jmsg2(jcr, M_FATAL, 0, _("Storage daemon at \"%s:%d\" rejected Hello command\n"),
         sd->host(), sd->port());
      return 0;
   }
   return 1;
}
Beispiel #21
0
/*
 * Authenticate File daemon connection
 */
int authenticate_file_daemon(JCR *jcr)
{
   BSOCK *fd = jcr->file_bsock;
   CLIENTRES *client = jcr->res.client;
   char dirname[MAX_NAME_LENGTH];
   int tls_local_need = BNET_TLS_NONE;
   int tls_remote_need = BNET_TLS_NONE;
   int compatible = true;
   bool auth_success = false;

   /*
    * Send my name to the File daemon then do authentication
    */
   bstrncpy(dirname, director->name(), sizeof(dirname));
   bash_spaces(dirname);
   /* Timeout Hello after 1 min */
   btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
   if (!fd->fsend(hello, dirname)) {
      stop_bsock_timer(tid);
      Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon at \"%s:%d\". ERR=%s\n"),
           fd->host(), fd->port(), fd->bstrerror());
      return 0;
   }
   Dmsg1(dbglvl, "Sent: %s", fd->msg);

   /* TLS Requirement */
   if (client->tls_enable) {
     if (client->tls_require) {
        tls_local_need = BNET_TLS_REQUIRED;
     } else {
        tls_local_need = BNET_TLS_OK;
     }
   }

   if (client->tls_authenticate) {
      tls_local_need = BNET_TLS_REQUIRED;
   }

   auth_success = cram_md5_respond(fd, client->password, &tls_remote_need, &compatible);
   if (auth_success) {
      auth_success = cram_md5_challenge(fd, client->password, tls_local_need, compatible);
      if (!auth_success) {
         Dmsg1(dbglvl, "cram_auth failed for %s\n", fd->who());
      }
   } else {
      Dmsg1(dbglvl, "cram_get_auth failed for %s\n", fd->who());
   }
   if (!auth_success) {
      stop_bsock_timer(tid);
      Dmsg0(dbglvl, _("Director and File daemon passwords or names not the same.\n"));
      Jmsg(jcr, M_FATAL, 0,
            _("Unable to authenticate with File daemon at \"%s:%d\". Possible causes:\n"
            "Passwords or names not the same or\n"
            "Maximum Concurrent Jobs exceeded on the FD or\n"
            "FD networking messed up (restart daemon).\n"
            "Please see " MANUAL_AUTH_URL " for help.\n"),
            fd->host(), fd->port());
      return 0;
   }

   /* Verify that the remote host is willing to meet our TLS requirements */
   if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
      stop_bsock_timer(tid);
      Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD \"%s:%s\" did not advertise required TLS support.\n"),
           fd->who(), fd->host());
      return 0;
   }

   /* Verify that we are willing to meet the remote host's requirements */
   if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
      stop_bsock_timer(tid);
      Jmsg(jcr, M_FATAL, 0, _("Authorization problem: FD at \"%s:%d\" requires TLS.\n"),
           fd->host(), fd->port());
      return 0;
   }

   /* Is TLS Enabled? */
   if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
      /* Engage TLS! Full Speed Ahead! */
      if (!bnet_tls_client(client->tls_ctx, fd, client->tls_allowed_cns)) {
         stop_bsock_timer(tid);
         Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\".\n"),
              fd->host(), fd->port());
         return 0;
      }
      if (client->tls_authenticate) {        /* tls authentication only? */
         fd->free_tls();                     /* yes, shutdown tls */
      }
   }

   Dmsg1(116, ">filed: %s", fd->msg);
   if (fd->recv() <= 0) {
      stop_bsock_timer(tid);
      Dmsg1(dbglvl, _("Bad response from File daemon to Hello command: ERR=%s\n"),
         bnet_strerror(fd));
      Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon at \"%s:%d\" to Hello command: ERR=%s\n"),
         fd->host(), fd->port(), fd->bstrerror());
      return 0;
   }
   Dmsg1(110, "<filed: %s", fd->msg);
   stop_bsock_timer(tid);
   jcr->FDVersion = 0;
   if (!bstrncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) &&
       sscanf(fd->msg, FDOKnewHello, &jcr->FDVersion) != 1) {
      Dmsg0(dbglvl, _("File daemon rejected Hello command\n"));
      Jmsg(jcr, M_FATAL, 0, _("File daemon at \"%s:%d\" rejected Hello command\n"),
           fd->host(), fd->port());
      return 0;
   }
   return 1;
}
Beispiel #22
0
/*
 * Common routine for both label and relabel
 */
static int do_label(UAContext *ua, const char *cmd, bool relabel)
{
   USTORERES store;
   BSOCK *sd;
   char dev_name[MAX_NAME_LENGTH];
   MEDIA_DBR mr, omr;
   POOL_DBR pr;
   bool print_reminder = true;
   bool label_barcodes = false;
   bool label_encrypt = false;
   int ok = FALSE;
   int i, j;
   int drive;
   bool media_record_exists = false;
   static const char *barcode_keywords[] = {
      "barcode",
      "barcodes",
      NULL
   };

   memset(&pr, 0, sizeof(pr));
   if (!open_client_db(ua)) {
      return 1;
   }

   /*
    * Look for one of the barcode keywords
    */
   if (!relabel && (i = find_arg_keyword(ua, barcode_keywords)) >= 0) {
      /*
       * Now find the keyword in the list
       */
      if ((j = find_arg(ua, barcode_keywords[i])) > 0) {
         *ua->argk[j] = 0;      /* zap barcode keyword */
      }
      label_barcodes = true;
   }

   /*
    * Look for the encrypt keyword
    */
   if ((i = find_arg(ua, "encrypt")) > 0) {
      *ua->argk[i] = 0;         /* zap encrypt keyword */
      label_encrypt = true;
   }

   store.store = get_storage_resource(ua, true, label_barcodes);
   if (!store.store) {
      return 1;
   }

   switch (store.store->Protocol) {
   case APT_NDMPV2:
   case APT_NDMPV3:
   case APT_NDMPV4:
      /*
       * See if the user selected a NDMP storage device but its
       * handled by a native Bareos storage daemon e.g. we have
       * a paired_storage pointer.
       */
      if (store.store->paired_storage) {
         store.store = store.store->paired_storage;
      } else {
         ua->warning_msg(_("Storage has non-native protocol.\n"));
         return 1;
      }
      break;
   default:
      break;
   }

   pm_strcpy(store.store_source, _("command line"));
   set_wstorage(ua->jcr, &store);
   drive = get_storage_drive(ua, store.store);

   if (label_barcodes) {
      label_from_barcodes(ua, drive, label_encrypt);
      return 1;
   }

   /*
    * If relabel get name of Volume to relabel
    */
   if (relabel) {
      /*
       * Check for oldvolume=name
       */
      i = find_arg_with_value(ua, "oldvolume");
      if (i >= 0) {
         bstrncpy(omr.VolumeName, ua->argv[i], sizeof(omr.VolumeName));
         if (db_get_media_record(ua->jcr, ua->db, &omr)) {
            goto checkVol;
         }
         ua->error_msg("%s", db_strerror(ua->db));
      }
      /*
       * No keyword or Vol not found, ask user to select
       */
      if (!select_media_dbr(ua, &omr)) {
         return 1;
      }

      /*
       * Require Volume to be Purged or Recycled
       */
checkVol:
      if (!bstrcmp(omr.VolStatus, "Purged") && !bstrcmp(omr.VolStatus, "Recycle")) {
         ua->error_msg(_("Volume \"%s\" has VolStatus %s. It must be Purged or Recycled before relabeling.\n"),
            omr.VolumeName, omr.VolStatus);
         return 1;
      }
   }

   /*
    * Check for volume=NewVolume
    */
   i = find_arg_with_value(ua, "volume");
   if (i >= 0) {
      pm_strcpy(ua->cmd, ua->argv[i]);
      goto checkName;
   }

   /*
    * Get a new Volume name
    */
   for ( ;; ) {
      media_record_exists = false;
      if (!get_cmd(ua, _("Enter new Volume name: "))) {
         return 1;
      }
checkName:
      if (!is_volume_name_legal(ua, ua->cmd)) {
         continue;
      }

      /*
       * Search by Media name so set VolumeName and clear MediaId.
       */
      mr.MediaId = 0;
      bstrncpy(mr.VolumeName, ua->cmd, sizeof(mr.VolumeName));

      /*
       * If VolBytes are zero the Volume is not labeled
       */
      if (db_get_media_record(ua->jcr, ua->db, &mr)) {
         if (mr.VolBytes != 0) {
             ua->error_msg(_("Media record for new Volume \"%s\" already exists.\n"),
                mr.VolumeName);
             continue;
          }
          media_record_exists = true;
      }
      break;                          /* Got it */
   }

   /*
    * If autochanger, request slot
    */
   i = find_arg_with_value(ua, "slot");
   if (i >= 0) {
      mr.Slot = atoi(ua->argv[i]);
      if (mr.Slot < 0) {
         mr.Slot = 0;
      }
      mr.InChanger = mr.Slot > 0;  /* if slot give assume in changer */
   } else if (store.store->autochanger) {
      if (!get_pint(ua, _("Enter slot (0 or Enter for none): "))) {
         return 1;
      }
      mr.Slot = ua->pint32_val;
      if (mr.Slot < 0) {
         mr.Slot = 0;
      }
      mr.InChanger = mr.Slot > 0;  /* if slot give assume in changer */
   }
   set_storageid_in_mr(store.store, &mr);

   bstrncpy(mr.MediaType, store.store->media_type, sizeof(mr.MediaType));

   /*
    * Must select Pool if not already done
    */
   if (pr.PoolId == 0) {
      memset(&pr, 0, sizeof(pr));
      if (!select_pool_dbr(ua, &pr)) {
         return 1;
      }
   }

   /*
    * See if we need to generate a new passphrase for hardware encryption.
    */
   if (label_encrypt) {
      ua->info_msg(_("Generating new hardware encryption key\n"));
      if (!generate_new_encryption_key(ua, &mr)) {
         return 1;
      }
   }

   ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists, drive);

   if (ok) {
      sd = ua->jcr->store_bsock;
      if (relabel) {
         /*
          * Delete the old media record
          */
         if (!db_delete_media_record(ua->jcr, ua->db, &omr)) {
            ua->error_msg(_("Delete of Volume \"%s\" failed. ERR=%s"),
               omr.VolumeName, db_strerror(ua->db));
         } else {
            ua->info_msg(_("Old volume \"%s\" deleted from catalog.\n"),
               omr.VolumeName);
            /*
             * Update the number of Volumes in the pool
             */
            pr.NumVols--;
            if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
               ua->error_msg("%s", db_strerror(ua->db));
            }
         }
      }
      if (ua->automount) {
         bstrncpy(dev_name, store.store->dev_name(), sizeof(dev_name));
         ua->info_msg(_("Requesting to mount %s ...\n"), dev_name);
         bash_spaces(dev_name);
         sd->fsend("mount %s drive=%d", dev_name, drive);
         unbash_spaces(dev_name);

         /*
          * We use bget_dirmsg here and not bnet_recv because as part of
          * the mount request the stored can request catalog information for
          * any plugin who listens to the bsdEventLabelVerified event.
          * As we don't want to loose any non protocol data e.g. errors
          * without a 3xxx prefix we set the allow_any_message of
          * bget_dirmsg to true and as such is behaves like a normal
          * bnet_recv for any non protocol messages.
          */
         while (bget_dirmsg(sd, true) >= 0) {
            ua->send_msg("%s", sd->msg);

            /*
             * Here we can get
             *  3001 OK mount. Device=xxx      or
             *  3001 Mounted Volume vvvv
             *  3002 Device "DVD-Writer" (/dev/hdc) is mounted.
             *  3906 is cannot mount non-tape
             * So for those, no need to print a reminder
             */
            if (bstrncmp(sd->msg, "3001 ", 5) ||
                bstrncmp(sd->msg, "3002 ", 5) ||
                bstrncmp(sd->msg, "3906 ", 5)) {
               print_reminder = false;
            }
         }
      }
   }

   if (print_reminder) {
      ua->info_msg(_("Do not forget to mount the drive!!!\n"));
   }

   close_sd_bsock(ua);

   return 1;
}
Beispiel #23
0
/*
 * Authenticate Director
 */
int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons)
{
   BSOCK *dir = jcr->dir_bsock;
   int tls_local_need = BNET_TLS_NONE;
   int tls_remote_need = BNET_TLS_NONE;
   bool tls_authenticate;
   int compatible = true;
   char bashed_name[MAX_NAME_LENGTH];
   char *password;
   TLS_CONTEXT *tls_ctx = NULL;

   /*
    * Send my name to the Director then do authentication
    */
   if (cons) {
      bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name));
      bash_spaces(bashed_name);
      password = cons->password;
      /* TLS Requirement */
      if (cons->tls_enable) {
         if (cons->tls_require) {
            tls_local_need = BNET_TLS_REQUIRED;
         } else {
            tls_local_need = BNET_TLS_OK;
         }
      }
      if (cons->tls_authenticate) {
         tls_local_need = BNET_TLS_REQUIRED;
      }
      tls_authenticate = cons->tls_authenticate;
      tls_ctx = cons->tls_ctx;
   } else {
      bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
      password = director->password;
      /* TLS Requirement */
      if (director->tls_enable) {
         if (director->tls_require) {
            tls_local_need = BNET_TLS_REQUIRED;
         } else {
            tls_local_need = BNET_TLS_OK;
         }
      }

      if (director->tls_authenticate) {
         tls_local_need = BNET_TLS_REQUIRED;
      }
      tls_authenticate = director->tls_authenticate;
      tls_ctx = director->tls_ctx;
   }


   /* Timeout Hello after 5 mins */
   btimer_t *tid = start_bsock_timer(dir, 60 * 5);
   dir->fsend(hello, bashed_name);

   if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) ||
       !cram_md5_challenge(dir, password, tls_local_need, compatible)) {
      goto bail_out;
   }

   /* Verify that the remote host is willing to meet our TLS requirements */
   if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
      sendit(_("Authorization problem:"
             " Remote server did not advertise required TLS support.\n"));
      goto bail_out;
   }

   /* Verify that we are willing to meet the remote host's requirements */
   if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
      sendit(_("Authorization problem:"
             " Remote server requires TLS.\n"));
      goto bail_out;
   }

   /* Is TLS Enabled? */
   if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
      /* Engage TLS! Full Speed Ahead! */
      if (!bnet_tls_client(tls_ctx, dir, NULL)) {
         sendit(_("TLS negotiation failed\n"));
         goto bail_out;
      }
      if (tls_authenticate) {           /* Authenticate only? */
         dir->free_tls();               /* yes, shutdown tls */
      }
   }

   /*
    * It's possible that the TLS connection will
    * be dropped here if an invalid client certificate was presented
    */
   Dmsg1(6, ">dird: %s", dir->msg);
   if (dir->recv() <= 0) {
      senditf(_("Bad response to Hello command: ERR=%s\n"),
         dir->bstrerror());
      goto bail_out;
   }

   Dmsg1(10, "<dird: %s", dir->msg);
   if (!bstrncmp(dir->msg, OKhello, sizeof(OKhello)-1)) {
      sendit(_("Director rejected Hello command\n"));
      goto bail_out;
   } else {
      sendit(dir->msg);
   }
   stop_bsock_timer(tid);
   return 1;

bail_out:
   stop_bsock_timer(tid);
   sendit( _("Director authorization problem.\n"
             "Most likely the passwords do not agree.\n"
             "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n"
             "Please see " MANUAL_AUTH_URL " for help.\n"));
   return 0;
}
static int
ssh_parse_args(obfsproxyssh_client_session_t *session, const char * args)
{
	obfsproxyssh_t *state = session->client->state;
	struct tagbstring hkey_rsa_prefix = bsStatic("hostkey-rsa=");
	struct tagbstring hkey_dss_prefix = bsStatic("hostkey-dsa=");
	struct tagbstring user_prefix = bsStatic("user="******"privkey=");
	struct tagbstring orport_prefix = bsStatic("orport=");
	struct tagbstring arg_str;
	struct bstrList *arg_list;
	bstring tmp;
	int i;

	/*
	 * Arguments are passed in as a single NULL terminated string,
	 * separated by ";" (Eg: "rocks=20;height=5.6m").
	 *
	 * Supported args:
	 *  * "hostkey-rsa=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX"
	 *  * "hostkey-dsa=YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY:YY"
	 *  * "user=USERNAME"
	 *  * "privkey=PRIVATEKEY" "PEM" format RSA key, with the header/footer/
	 *  *                      newlines stripped.
	 *  * "orport=XXXXX" Port on the remote peer's loopback interface that
	 *                   Tor is listening on (Temporary argument since once
	 *                   there's an actual server implementation it should
	 *                   handle that automatically).
	 */

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
	btfromcstr(arg_str, args);
	arg_list = bsplit(&arg_str, ';');
	for (i = 0; i < arg_list->qty; i++) {
		if (0 == bstrncmp(&hkey_rsa_prefix, arg_list->entry[i],
					blength(&hkey_rsa_prefix))) {
			session->hostkey_rsa = bmidstr(arg_list->entry[i],
					blength(&hkey_rsa_prefix),
					blength(arg_list->entry[i]) -
					blength(&hkey_rsa_prefix));
		} else if (0 == bstrncmp(&hkey_dss_prefix, arg_list->entry[i],
					blength(&hkey_dss_prefix))) {
			session->hostkey_dss = bmidstr(arg_list->entry[i],
					blength(&hkey_dss_prefix),
					blength(arg_list->entry[i]) -
					blength(&hkey_dss_prefix));
		} else if (0 == bstrncmp(&user_prefix, arg_list->entry[i],
					blength(&user_prefix))) {
			session->user = bmidstr(arg_list->entry[i],
					blength(&user_prefix),
					blength(arg_list->entry[i]) -
					blength(&user_prefix));
		} else if (0 == bstrncmp(&privkey_prefix, arg_list->entry[i],
					blength(&privkey_prefix))) {
			tmp = bmidstr(arg_list->entry[i],
					blength(&privkey_prefix),
					blength(arg_list->entry[i]) -
					blength(&user_prefix));
			session->privkey_pem = ssh_arg_to_privkey(tmp);
			bdestroy(tmp);
		} else if (0 == bstrncmp(&orport_prefix, arg_list->entry[i],
					blength(&orport_prefix))) {
			tmp = bmidstr(arg_list->entry[i],
					blength(&orport_prefix),
					blength(arg_list->entry[i]) -
					blength(&orport_prefix));
#pragma GCC diagnostic ignored "-Wnonnull"
			session->orport = atoi(bdata(tmp));
			bdestroy(tmp);
		}
	}
#pragma GCC diagnostic pop

	bstrListDestroy(arg_list);

	if (NULL == session->hostkey_rsa && NULL == session->hostkey_dss)
		return -1;

	if (NULL == session->user || NULL == session->privkey_pem ||
			0 == session->orport)
		return -1;

	/* Generate libssh compatible keys from the PEM */
	session->privkey = read_rsa_private_key_from_memory(
			bdata(session->privkey_pem),
			blength(session->privkey_pem));
	if (NULL == session->privkey) {
		log_f(state, "SOCKS: Error: %s Unable to decode private key",
					bdata(session->socks_addr));
		return -1;
	}

	return 0;
}
Beispiel #25
0
/*
 * We read an ANSI label and compare the Volume name. We require
 * a VOL1 record of 80 characters followed by a HDR1 record containing
 * BAREOS.DATA in the filename field. We then read up to 3 more
 * header records (they are not required) and an EOF, at which
 * point, all is good.
 *
 * Returns:
 *    VOL_OK            Volume name OK
 *    VOL_NO_LABEL      No ANSI label on Volume
 *    VOL_IO_ERROR      I/O error on read
 *    VOL_NAME_ERROR    Wrong name in VOL1 record
 *    VOL_LABEL_ERROR   Probably an ANSI label, but something wrong
 *
 */
int read_ansi_ibm_label(DCR *dcr)
{
    DEVICE * volatile dev = dcr->dev;
    JCR *jcr = dcr->jcr;
    char label[80];                    /* tape label */
    int status, i;
    char *VolName = dcr->VolumeName;
    bool ok = false;

    /*
     * Read VOL1, HDR1, HDR2 labels, but ignore the data
     *  If tape read the following EOF mark, on disk do
     *  not read.
     */
    Dmsg0(100, "Read ansi label.\n");
    if (!dev->is_tape()) {
        return VOL_OK;
    }

    dev->label_type = B_BAREOS_LABEL;  /* assume Bareos label */

    /* Read a maximum of 5 records VOL1, HDR1, ... HDR4 */
    for (i=0; i < 6; i++) {
        do {
            status = dev->read(label, sizeof(label));
        } while (status == -1 && errno == EINTR);
        if (status < 0) {
            berrno be;
            dev->clrerror(-1);
            Dmsg1(100, "Read device got: ERR=%s\n", be.bstrerror());
            Mmsg2(jcr->errmsg, _("Read error on device %s in ANSI label. ERR=%s\n"),
                  dev->dev_name, be.bstrerror());
            Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
            dev->VolCatInfo.VolCatErrors++;
            return VOL_IO_ERROR;
        }
        if (status == 0) {
            if (dev->at_eof()) {
                dev->set_eot();           /* second eof, set eot bit */
                Dmsg0(100, "EOM on ANSI label\n");
                Mmsg0(jcr->errmsg, _("Insane! End of tape while reading ANSI label.\n"));
                return VOL_LABEL_ERROR;   /* at EOM this shouldn't happen */
            } else {
                dev->set_ateof();        /* set eof state */
            }
        }
        switch (i) {
        case 0:                         /* Want VOL1 label */
            if (status == 80) {
                if (bstrncmp("VOL1", label, 4)) {
                    ok = true;
                    dev->label_type = B_ANSI_LABEL;
                    Dmsg0(100, "Got ANSI VOL1 label\n");
                } else {
                    /* Try EBCDIC */
                    ebcdic_to_ascii(label, label, sizeof(label));
                    if (bstrncmp("VOL1", label, 4)) {
                        ok = true;;
                        dev->label_type = B_IBM_LABEL;
                        Dmsg0(100, "Found IBM label.\n");
                        Dmsg0(100, "Got IBM VOL1 label\n");
                    }
                }
            }
            if (!ok) {
                Dmsg0(100, "No VOL1 label\n");
                Mmsg0(jcr->errmsg, _("No VOL1 label while reading ANSI/IBM label.\n"));
                return VOL_NO_LABEL;   /* No ANSI label */
            }


            /* Compare Volume Names allow special wild card */
            if (VolName && *VolName && *VolName != '*') {
                if (!same_label_names(VolName, &label[4])) {
                    char *p = &label[4];
                    char *q;

                    free_volume(dev);
                    /* Store new Volume name */
                    q = dev->VolHdr.VolumeName;
                    for (int i=0; *p != ' ' && i < 6; i++) {
                        *q++ = *p++;
                    }
                    *q = 0;
                    Dmsg0(100, "Call reserve_volume\n");
                    /* ***FIXME***  why is this reserve_volume() needed???? KES */
                    reserve_volume(dcr, dev->VolHdr.VolumeName);
                    dev = dcr->dev;            /* may have changed in reserve_volume */
                    Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName);
                    Mmsg2(jcr->errmsg, _("Wanted ANSI Volume \"%s\" got \"%s\"\n"), VolName, dev->VolHdr.VolumeName);
                    return VOL_NAME_ERROR;
                }
            }
            break;
        case 1:
            if (dev->label_type == B_IBM_LABEL) {
                ebcdic_to_ascii(label, label, sizeof(label));
            }
            if (status != 80 || !bstrncmp("HDR1", label, 4)) {
                Dmsg0(100, "No HDR1 label\n");
                Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
                return VOL_LABEL_ERROR;
            }
            if (!bstrncmp("BAREOS.DATA", &label[4], 11)) {
                Dmsg1(100, "HD1 not Bareos label. Wanted  BAREOS.DATA got %11s\n",
                      &label[4]);
                Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bareos.\n"),
                      dev->VolHdr.VolumeName);
                return VOL_NAME_ERROR;     /* Not a Bareos label */
            }
            Dmsg0(100, "Got HDR1 label\n");
            break;
        case 2:
            if (dev->label_type == B_IBM_LABEL) {
                ebcdic_to_ascii(label, label, sizeof(label));
            }
            if (status != 80 || !bstrncmp("HDR2", label, 4)) {
                Dmsg0(100, "No HDR2 label\n");
                Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n"));
                return VOL_LABEL_ERROR;
            }
            Dmsg0(100, "Got ANSI HDR2 label\n");
            break;
        default:
            if (status == 0) {
                Dmsg0(100, "ANSI label OK\n");
                return VOL_OK;
            }
            if (dev->label_type == B_IBM_LABEL) {
                ebcdic_to_ascii(label, label, sizeof(label));
            }
            if (status != 80 || !bstrncmp("HDR", label, 3)) {
                Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n");
                Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n"));
                return VOL_LABEL_ERROR;
            }
            Dmsg0(100, "Got HDR label\n");
            break;
        }
    }
    Dmsg0(100, "Too many records in ANSI/IBM label.\n");
    Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n"));
    return VOL_LABEL_ERROR;
}