Пример #1
0
/**
 * @brief Convert a public key to a base64 encoded key.
 *
 * @param[in] key       The key to hash
 *
 * @param[out] b64_key  A pointer to store the allocated base64 encoded key. You
 *                      need to free the buffer.
 *
 * @return              SSH_OK on success, SSH_ERROR on error.
 *
 * @see ssh_string_free_char()
 */
int ssh_pki_export_pubkey_base64(const ssh_key key,
                                 char **b64_key)
{
    ssh_string key_blob;
    unsigned char *b64;

    if (key == NULL || b64_key == NULL) {
        return SSH_ERROR;
    }

    key_blob = pki_publickey_to_blob(key);
    if (key_blob == NULL) {
        return SSH_ERROR;
    }

    b64 = bin_to_base64(ssh_string_data(key_blob), ssh_string_len(key_blob));
    ssh_string_free(key_blob);
    if (b64 == NULL) {
        return SSH_ERROR;
    }

    *b64_key = (char *)b64;

    return SSH_OK;
}
Пример #2
0
void test_bin_to_base64()
{
   int x = 0, compatible = 1, len;
   char res[100];
   
   while(strcmp(test_bin_to_base64_data[x].test_str, "") != 0) {
      len = bin_to_base64(res, 100, test_bin_to_base64_data[x].test_str, 
                          strlen(test_bin_to_base64_data[x].test_str), compatible);
      CU_ASSERT(strcmp(res, test_bin_to_base64_data[x].base64_result) == 0);
      x++;
   }
}
Пример #3
0
/* Respond to challenge from other end */
bool cram_md5_respond(BSOCK *bs, const char *password, int *tls_remote_need, bool *compatible)
{
   char chal[MAXSTRING];
   uint8_t hmac[20];

   *compatible = false;
   if (bs->recv() <= 0) {
      bmicrosleep(5, 0);
      return false;
   }
   if (bs->msglen >= MAXSTRING) {
      Dmsg1(dbglvl, "Msg too long wanted auth cram... Got: %s", bs->msg);
      bmicrosleep(5, 0);
      return false;
   }
   Dmsg1(100, "cram-get received: %s", bs->msg);
   if (sscanf(bs->msg, "auth cram-md5c %s ssl=%d", chal, tls_remote_need) == 2) {
      *compatible = true;
   } else if (sscanf(bs->msg, "auth cram-md5 %s ssl=%d", chal, tls_remote_need) != 2) {
      if (sscanf(bs->msg, "auth cram-md5 %s\n", chal) != 1) {
         Dmsg1(dbglvl, "Cannot scan challenge: %s", bs->msg);
         bs->fsend(_("1999 Authorization failed.\n"));
         bmicrosleep(5, 0);
         return false;
      }
   }

   hmac_md5((uint8_t *)chal, strlen(chal), (uint8_t *)password, strlen(password), hmac);
   bs->msglen = bin_to_base64(bs->msg, 50, (char *)hmac, 16, *compatible) + 1;
// Dmsg3(100, "get_auth: chal=%s pw=%s hmac=%s\n", chal, password, bs->msg);
   if (!bs->send()) {
      Dmsg1(dbglvl, "Send challenge failed. ERR=%s\n", bs->bstrerror());
      return false;
   }
   Dmsg1(99, "sending resp to challenge: %s\n", bs->msg);
   if (bs->wait_data(180) <= 0 || bs->recv() <= 0) {
      Dmsg1(dbglvl, "Receive chanllenge response failed. ERR=%s\n", bs->bstrerror());
      bmicrosleep(5, 0);
      return false;
   }
   if (bstrcmp(bs->msg, "1000 OK auth\n")) {
      return true;
   }
   Dmsg1(dbglvl, "Received bad response: %s\n", bs->msg);
   bmicrosleep(5, 0);
   return false;
}
Пример #4
0
/*
 * Calculate the chksum of a whole file and updates:
 * - digest
 * - digest_stream
 * - digest_buffer
 * - digest_name
 *
 * Returns: true   if digest calculation succeeded.
 *          false  if digest calculation failed.
 */
static bool calculate_file_chksum(JCR *jcr, FF_PKT *ff_pkt, DIGEST **digest,
                                  int *digest_stream, char **digest_buf, const char **digest_name)
{
   /*
    * Create our digest context.
    * If this fails, the digest will be set to NULL and not used.
    */
   if (ff_pkt->flags & FO_MD5) {
      *digest = crypto_digest_new(jcr, CRYPTO_DIGEST_MD5);
      *digest_stream = STREAM_MD5_DIGEST;
   } else if (ff_pkt->flags & FO_SHA1) {
      *digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA1);
      *digest_stream = STREAM_SHA1_DIGEST;
   } else if (ff_pkt->flags & FO_SHA256) {
      *digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA256);
      *digest_stream = STREAM_SHA256_DIGEST;
   } else if (ff_pkt->flags & FO_SHA512) {
      *digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA512);
      *digest_stream = STREAM_SHA512_DIGEST;
   }

   /*
    * compute MD5 or SHA1 hash
    */
   if (*digest) {
      uint32_t size;
      char md[CRYPTO_DIGEST_MAX_SIZE];

      size = sizeof(md);
      if (digest_file(jcr, ff_pkt, *digest) != 0) {
         jcr->JobErrors++;
         return false;
      }

      if (crypto_digest_finalize(*digest, (uint8_t *)md, &size)) {
         *digest_buf = (char *)malloc(BASE64_SIZE(size));
         *digest_name = crypto_digest_name(*digest);

         bin_to_base64(*digest_buf, BASE64_SIZE(size), md, size, true);
      }
   }

   return true;
}
Пример #5
0
/*
 * Generate a new encryption key for use in volume encryption.
 * We don't ask the user for a encryption key but generate a semi
 * random passphrase of the wanted length which is way stronger.
 * When the config has a wrap key we use that to wrap the newly
 * created passphrase using RFC3394 aes wrap and always convert
 * the passphrase into a base64 encoded string. This key is
 * stored in the database and is passed to the storage daemon
 * when needed. The storage daemon has the same wrap key per
 * director so it can unwrap the passphrase for use.
 *
 * Changing the wrap key will render any previously created
 * crypto keys useless so only change the wrap key after initial
 * setting when you know what you are doing and always store
 * the old key somewhere save so you can use bscrypto to
 * convert them for the new wrap key.
 */
static bool generate_new_encryption_key(UAContext *ua, MEDIA_DBR *mr)
{
   int length;
   char *passphrase;

   passphrase = generate_crypto_passphrase(DEFAULT_PASSPHRASE_LENGTH);
   if (!passphrase) {
      ua->error_msg(_("Failed to generate new encryption passphrase for Volume %s.\n"), mr->VolumeName);
      return false;
   }

   /*
    * See if we need to wrap the passphrase.
    */
   if (me->keyencrkey) {
      char *wrapped_passphrase;

      length = DEFAULT_PASSPHRASE_LENGTH + 8;
      wrapped_passphrase = (char *)malloc(length);
      memset(wrapped_passphrase, 0, length);
      aes_wrap((unsigned char *)me->keyencrkey,
               DEFAULT_PASSPHRASE_LENGTH / 8,
               (unsigned char *)passphrase,
               (unsigned char *)wrapped_passphrase);

      free(passphrase);
      passphrase = wrapped_passphrase;
   } else {
      length = DEFAULT_PASSPHRASE_LENGTH;
   }

   /*
    * The passphrase is always base64 encoded.
    */
   bin_to_base64(mr->EncrKey, sizeof(mr->EncrKey), passphrase, length, true);

   free(passphrase);
   return true;
}
Пример #6
0
bool get_or_create_fileset_record(JCR *jcr)
{
   FILESET_DBR fsr;
   /*
    * Get or Create FileSet record
    */
   memset(&fsr, 0, sizeof(FILESET_DBR));
   bstrncpy(fsr.FileSet, jcr->res.fileset->hdr.name, sizeof(fsr.FileSet));
   if (jcr->res.fileset->have_MD5) {
      struct MD5Context md5c;
      unsigned char digest[MD5HashSize];
      memcpy(&md5c, &jcr->res.fileset->md5c, sizeof(md5c));
      MD5Final(digest, &md5c);
      /*
       * Keep the flag (last arg) set to false otherwise old FileSets will
       * get new MD5 sums and the user will get Full backups on everything
       */
      bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
      bstrncpy(jcr->res.fileset->MD5, fsr.MD5, sizeof(jcr->res.fileset->MD5));
   } else {
      Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
   }
   if (!jcr->res.fileset->ignore_fs_changes ||
       !db_get_fileset_record(jcr, jcr->db, &fsr)) {
      if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
         Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
            fsr.FileSet, db_strerror(jcr->db));
         return false;
      }
   }
   jcr->jr.FileSetId = fsr.FileSetId;
   bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
   Dmsg2(119, "Created FileSet %s record %u\n", jcr->res.fileset->hdr.name,
      jcr->jr.FileSetId);
   return true;
}
Пример #7
0
/*
 * Note, we receive the whole attribute record, but we select out only the stat
 * packet, VolSessionId, VolSessionTime, FileIndex, file type, and file name to
 * store in the catalog.
 */
static void update_attribute(JCR *jcr, char *msg, int32_t msglen)
{
   unser_declare;
   uint32_t VolSessionId, VolSessionTime;
   int32_t Stream;
   uint32_t FileIndex;
   char *p;
   int len;
   char *fname, *attr;
   ATTR_DBR *ar = NULL;
   uint32_t reclen;

   /*
    * Start transaction allocates jcr->attr and jcr->ar if needed
    */
   db_start_transaction(jcr, jcr->db);     /* start transaction if not already open */
   ar = jcr->ar;

   /*
    * Start by scanning directly in the message buffer to get Stream
    * there may be a cached attr so we cannot yet write into
    * jcr->attr or jcr->ar
    */
   p = msg;
   skip_nonspaces(&p);                /* UpdCat */
   skip_spaces(&p);
   skip_nonspaces(&p);                /* Job=nnn */
   skip_spaces(&p);
   skip_nonspaces(&p);                /* "FileAttributes" */
   p += 1;

   /*
    * The following "SD header" fields are serialized
    */
   unser_begin(p, 0);
   unser_uint32(VolSessionId);        /* VolSessionId */
   unser_uint32(VolSessionTime);      /* VolSessionTime */
   unser_int32(FileIndex);            /* FileIndex */
   unser_int32(Stream);               /* Stream */
   unser_uint32(reclen);              /* Record length */
   p += unser_length(p);              /* Raw record follows */

   /**
    * At this point p points to the raw record, which varies according
    *  to what kind of a record (Stream) was sent.  Note, the integer
    *  fields at the beginning of these "raw" records are in ASCII with
    *  spaces between them so one can use scanf or manual scanning to
    *  extract the fields.
    *
    * File Attributes
    *   File_index
    *   File type
    *   Filename (full path)
    *   Encoded attributes
    *   Link name (if type==FT_LNK or FT_LNKSAVED)
    *   Encoded extended-attributes (for Win32)
    *   Delta sequence number (32 bit int)
    *
    * Restore Object
    *   File_index
    *   File_type
    *   Object_index
    *   Object_len (possibly compressed)
    *   Object_full_len (not compressed)
    *   Object_compression
    *   Plugin_name
    *   Object_name
    *   Binary Object data
    */

   Dmsg1(400, "UpdCat msg=%s\n", msg);
   Dmsg5(400, "UpdCat VolSessId=%d VolSessT=%d FI=%d Strm=%d reclen=%d\n",
         VolSessionId, VolSessionTime, FileIndex, Stream, reclen);

   jcr->SDJobBytes += reclen; /* update number of bytes transferred for quotas */

   /*
    * Depending on the stream we are handling dispatch.
    */
   switch (Stream) {
   case STREAM_UNIX_ATTRIBUTES:
   case STREAM_UNIX_ATTRIBUTES_EX:
      if (jcr->cached_attribute) {
         Dmsg2(400, "Cached attr. Stream=%d fname=%s\n", ar->Stream, ar->fname);
         if (!db_create_attributes_record(jcr, jcr->db, ar)) {
            Jmsg1(jcr, M_FATAL, 0, _("Attribute create error: ERR=%s"), db_strerror(jcr->db));
         }
         jcr->cached_attribute = false;
      }

      /*
       * Any cached attr is flushed so we can reuse jcr->attr and jcr->ar
       */
      jcr->attr = check_pool_memory_size(jcr->attr, msglen);
      memcpy(jcr->attr, msg, msglen);
      p = jcr->attr - msg + p;         /* point p into jcr->attr */
      skip_nonspaces(&p);              /* skip FileIndex */
      skip_spaces(&p);
      ar->FileType = str_to_int32(p);
      skip_nonspaces(&p);              /* skip FileType */
      skip_spaces(&p);
      fname = p;
      len = strlen(fname);             /* length before attributes */
      attr = &fname[len+1];
      ar->DeltaSeq = 0;
      if (ar->FileType == FT_REG) {
         p = attr + strlen(attr) + 1;  /* point to link */
         p = p + strlen(p) + 1;        /* point to extended attributes */
         p = p + strlen(p) + 1;        /* point to delta sequence */
         /*
          * Older FDs don't have a delta sequence, so check if it is there
          */
         if (p - jcr->attr < msglen) {
            ar->DeltaSeq = str_to_int32(p); /* delta_seq */
         }
      }

      Dmsg2(400, "dird<stored: stream=%d %s\n", Stream, fname);
      Dmsg1(400, "dird<stored: attr=%s\n", attr);

      ar->attr = attr;
      ar->fname = fname;
      if (ar->FileType == FT_DELETED) {
         ar->FileIndex = 0;     /* special value */
      } else {
         ar->FileIndex = FileIndex;
      }
      ar->Stream = Stream;
      ar->link = NULL;
      if (jcr->mig_jcr) {
         ar->JobId = jcr->mig_jcr->JobId;
      } else {
         ar->JobId = jcr->JobId;
      }
      ar->Digest = NULL;
      ar->DigestType = CRYPTO_DIGEST_NONE;
      jcr->cached_attribute = true;

      Dmsg2(400, "dird<filed: stream=%d %s\n", Stream, fname);
      Dmsg1(400, "dird<filed: attr=%s\n", attr);
      break;
   case STREAM_RESTORE_OBJECT: {
      ROBJECT_DBR ro;

      memset(&ro, 0, sizeof(ro));
      ro.Stream = Stream;
      ro.FileIndex = FileIndex;
      if (jcr->mig_jcr) {
         ro.JobId = jcr->mig_jcr->JobId;
      } else {
         ro.JobId = jcr->JobId;
      }

      Dmsg1(100, "Robj=%s\n", p);

      skip_nonspaces(&p);                  /* skip FileIndex */
      skip_spaces(&p);
      ro.FileType = str_to_int32(p);        /* FileType */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_index = str_to_int32(p);    /* Object Index */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_len = str_to_int32(p);      /* object length possibly compressed */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_full_len = str_to_int32(p); /* uncompressed object length */
      skip_nonspaces(&p);
      skip_spaces(&p);
      ro.object_compression = str_to_int32(p); /* compression */
      skip_nonspaces(&p);
      skip_spaces(&p);

      ro.plugin_name = p;                      /* point to plugin name */
      len = strlen(ro.plugin_name);
      ro.object_name = &ro.plugin_name[len+1]; /* point to object name */
      len = strlen(ro.object_name);
      ro.object = &ro.object_name[len+1];      /* point to object */
      ro.object[ro.object_len] = 0;            /* add zero for those who attempt printing */

      Dmsg7(100, "oname=%s stream=%d FT=%d FI=%d JobId=%d, obj_len=%d\nobj=\"%s\"\n",
            ro.object_name, ro.Stream, ro.FileType, ro.FileIndex, ro.JobId,
            ro.object_len, ro.object);

      /*
       * Store it.
       */
      if (!db_create_restore_object_record(jcr, jcr->db, &ro)) {
         Jmsg1(jcr, M_FATAL, 0, _("Restore object create error. %s"), db_strerror(jcr->db));
      }
      break;
   }
   default:
      if (crypto_digest_stream_type(Stream) != CRYPTO_DIGEST_NONE) {
         fname = p;
         if (ar->FileIndex != FileIndex) {
            Jmsg3(jcr, M_WARNING, 0, _("%s not same File=%d as attributes=%d\n"),
               stream_to_ascii(Stream), FileIndex, ar->FileIndex);
         } else {
            /*
             * Update digest in catalog
             */
            char digestbuf[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
            int len = 0;
            int type = CRYPTO_DIGEST_NONE;

            switch(Stream) {
            case STREAM_MD5_DIGEST:
               len = CRYPTO_DIGEST_MD5_SIZE;
               type = CRYPTO_DIGEST_MD5;
               break;
            case STREAM_SHA1_DIGEST:
               len = CRYPTO_DIGEST_SHA1_SIZE;
               type = CRYPTO_DIGEST_SHA1;
               break;
            case STREAM_SHA256_DIGEST:
               len = CRYPTO_DIGEST_SHA256_SIZE;
               type = CRYPTO_DIGEST_SHA256;
               break;
            case STREAM_SHA512_DIGEST:
               len = CRYPTO_DIGEST_SHA512_SIZE;
               type = CRYPTO_DIGEST_SHA512;
               break;
            default:
               /*
                * Never reached ...
                */
               Jmsg(jcr, M_ERROR, 0, _("Catalog error updating file digest. Unsupported digest stream type: %d"), Stream);
            }

            bin_to_base64(digestbuf, sizeof(digestbuf), fname, len, true);

            Dmsg3(400, "DigestLen=%d Digest=%s type=%d\n", strlen(digestbuf),
                  digestbuf, Stream);

            if (jcr->cached_attribute) {
               ar->Digest = digestbuf;
               ar->DigestType = type;

               Dmsg2(400, "Cached attr with digest. Stream=%d fname=%s\n", ar->Stream, ar->fname);

               /*
                * Update BaseFile table
                */
               if (!db_create_attributes_record(jcr, jcr->db, ar)) {
                  Jmsg1(jcr, M_FATAL, 0, _("attribute create error. %s"), db_strerror(jcr->db));
               }
               jcr->cached_attribute = false;
            } else {
               if (!db_add_digest_to_file_record(jcr, jcr->db, ar->FileId, digestbuf, type)) {
                  Jmsg(jcr, M_ERROR, 0, _("Catalog error updating file digest. %s"), db_strerror(jcr->db));
               }
            }
         }
      }
      break;
   }
}
Пример #8
0
/*
 * Verify attributes of the requested files on the Volume
 *
 */
void do_verify_volume(JCR *jcr)
{
   BSOCK *sd, *dir;
   POOLMEM *fname;                    /* original file name */
   POOLMEM *lname;                    /* link name */
   int32_t stream;
   uint32_t size;
   uint32_t VolSessionId, VolSessionTime, file_index;
   uint32_t record_file_index;
   char digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
   int type, stat;

   sd = jcr->store_bsock;
   if (!sd) {
      Jmsg(jcr, M_FATAL, 0, _("Storage command not issued before Verify.\n"));
      jcr->setJobStatus(JS_FatalError);
      return;
   }
   dir = jcr->dir_bsock;
   jcr->setJobStatus(JS_Running);

   LockRes();
   CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
   UnlockRes();
   uint32_t buf_size;
   if (client) {
      buf_size = client->max_network_buffer_size;
   } else {
      buf_size = 0;                   /* use default */
   }
   if (!sd->set_buffer_size(buf_size, BNET_SETBUF_WRITE)) {
      jcr->setJobStatus(JS_FatalError);
      return;
   }
   jcr->buf_size = sd->msglen;

   fname = get_pool_memory(PM_FNAME);
   lname = get_pool_memory(PM_FNAME);

   /*
    * Get a record from the Storage daemon
    */
   while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
      /*
       * First we expect a Stream Record Header
       */
      if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index,
          &stream, &size) != 5) {
         Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg);
         goto bail_out;
      }
      Dmsg3(30, "Got hdr: FilInx=%d Stream=%d size=%d.\n", file_index, stream, size);

      /*
       * Now we expect the Stream Data
       */
      if (bget_msg(sd) < 0) {
         Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), sd->bstrerror());
         goto bail_out;
      }
      if (size != ((uint32_t)sd->msglen)) {
         Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size);
         goto bail_out;
      }
      Dmsg2(30, "Got stream data %s, len=%d\n", stream_to_ascii(stream), sd->msglen);

      /* File Attributes stream */
      switch (stream) {
      case STREAM_UNIX_ATTRIBUTES:
      case STREAM_UNIX_ATTRIBUTES_EX:
         char *ap, *lp, *fp;

         Dmsg0(400, "Stream=Unix Attributes.\n");

         if ((int)sizeof_pool_memory(fname) < sd->msglen) {
            fname = realloc_pool_memory(fname, sd->msglen + 1);
         }

         if ((int)sizeof_pool_memory(lname) < sd->msglen) {
            lname = realloc_pool_memory(lname, sd->msglen + 1);
         }
         *fname = 0;
         *lname = 0;

         /*
          * An Attributes record consists of:
          *    File_index
          *    Type   (FT_types)
          *    Filename
          *    Attributes
          *    Link name (if file linked i.e. FT_LNK)
          *    Extended Attributes (if Win32)
          */
         if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) {
            Jmsg(jcr, M_FATAL, 0, _("Error scanning record header: %s\n"), sd->msg);
            Dmsg0(0, "\nError scanning header\n");
            goto bail_out;
         }
         Dmsg2(30, "Got Attr: FilInx=%d type=%d\n", record_file_index, type);
         ap = sd->msg;
         while (*ap++ != ' ')         /* skip record file index */
            ;
         while (*ap++ != ' ')         /* skip type */
            ;
         /* Save filename and position to attributes */
         fp = fname;
         while (*ap != 0) {
            *fp++  = *ap++;           /* copy filename to fname */
         }
         *fp = *ap++;                 /* terminate filename & point to attribs */

         Dmsg2(100, "File=%s Attr=%s\n", fname, ap);
         /* Skip to Link name */
         if (type == FT_LNK || type == FT_LNKSAVED) {
            lp = ap;
            while (*lp++ != 0) {
               ;
            }
            pm_strcat(lname, lp);        /* "save" link name */
         } else {
            *lname = 0;
         }
         jcr->lock();
         jcr->JobFiles++;
         jcr->num_files_examined++;
         pm_strcpy(jcr->last_fname, fname); /* last file examined */
         jcr->unlock();

         /*
          * Send file attributes to Director
          *   File_index
          *   Stream
          *   Verify Options
          *   Filename (full path)
          *   Encoded attributes
          *   Link name (if type==FT_LNK)
          * For a directory, link is the same as fname, but with trailing
          * slash. For a linked file, link is the link.
          */
         /* Send file attributes to Director */
         Dmsg2(200, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, fname);
         if (type == FT_LNK || type == FT_LNKSAVED) {
            stat = dir->fsend("%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
                          STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
                          0, ap, 0, lname, 0);
         /* for a deleted record, we set fileindex=0 */
         } else if (type == FT_DELETED)  {
            stat = dir->fsend("%d %d %s %s%c%s%c%c", 0,
                          STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
                          0, ap, 0, 0);
         } else {
            stat = dir->fsend("%d %d %s %s%c%s%c%c", jcr->JobFiles,
                          STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
                          0, ap, 0, 0);
         }
         Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
         if (!stat) {
            Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), dir->bstrerror());
            goto bail_out;
         }
         break;

      case STREAM_MD5_DIGEST:
         bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_MD5_SIZE, true);
         Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest);
         dir->fsend("%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_DIGEST, digest,
                    jcr->JobFiles);
         Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
         break;

      case STREAM_SHA1_DIGEST:
         bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA1_SIZE, true);
         Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, digest);
         dir->fsend("%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_DIGEST,
                    digest, jcr->JobFiles);
         Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
         break;

      case STREAM_SHA256_DIGEST:
         bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA256_SIZE, true);
         Dmsg2(400, "send inx=%d SHA256=%s\n", jcr->JobFiles, digest);
         dir->fsend("%d %d %s *SHA256-%d*", jcr->JobFiles, STREAM_SHA256_DIGEST,
                    digest, jcr->JobFiles);
         Dmsg2(20, "bfiled>bdird: SHA256 len=%d: msg=%s\n", dir->msglen, dir->msg);
         break;

      case STREAM_SHA512_DIGEST:
         bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA512_SIZE, true);
         Dmsg2(400, "send inx=%d SHA512=%s\n", jcr->JobFiles, digest);
         dir->fsend("%d %d %s *SHA512-%d*", jcr->JobFiles, STREAM_SHA512_DIGEST,
                    digest, jcr->JobFiles);
         Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg);
         break;

      /*
       * Restore stream object is counted, but not restored here
       */
      case STREAM_RESTORE_OBJECT:
         jcr->lock();
         jcr->JobFiles++;
         jcr->num_files_examined++;
         jcr->unlock();
         break;

      /* Ignore everything else */
      default:
         break;

      } /* end switch */
   } /* end while bnet_get */
   jcr->setJobStatus(JS_Terminated);
   goto ok_out;

bail_out:
   jcr->setJobStatus(JS_ErrorTerminated);

ok_out:
   if (jcr->compress_buf) {
      free(jcr->compress_buf);
      jcr->compress_buf = NULL;
   }
   free_pool_memory(fname);
   free_pool_memory(lname);
   Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
      jcr->JobBytes);
}
Пример #9
0
/**
 * @brief Write the current server as known in the known hosts file.
 *
 * This will create the known hosts file if it does not exist. You generaly use
 * it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN.
 *
 * @param[in]  session  The ssh session to use.
 *
 * @return              SSH_OK on success, SSH_ERROR on error.
 */
int ssh_write_knownhost(ssh_session session) {
  ssh_string pubkey;
  unsigned char *pubkey_64;
  char buffer[4096] = {0};
  FILE *file;
  char *dir;
  char *host;
  char *hostport;
  size_t len = 0;

  if (session->host == NULL) {
    ssh_set_error(session, SSH_FATAL,
        "Can't write host in known hosts if the hostname isn't known");
    return SSH_ERROR;
  }

  host = ssh_lowercase(session->host);
  /* If using a nonstandard port, save the host in the [host]:port format */
  if(session->port != 22){
    hostport = ssh_hostport(host,session->port);
    SAFE_FREE(host);
    host=hostport;
    hostport=NULL;
  }

  if (session->knownhosts == NULL) {
    if (ssh_options_apply(session) < 0) {
      ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file");
      return SSH_ERROR;
    }
  }

  if(session->current_crypto==NULL) {
  	ssh_set_error(session, SSH_FATAL, "No current crypto context");
  	return SSH_ERROR;
  }

  pubkey = session->current_crypto->server_pubkey;
  if(pubkey == NULL){
  	ssh_set_error(session, SSH_FATAL, "No public key present");
  	return SSH_ERROR;
  }

  /* Check if ~/.ssh exists and create it if not */
  dir = ssh_dirname(session->knownhosts);
  if (dir == NULL) {
    ssh_set_error(session, SSH_FATAL, "%s", strerror(errno));
    return -1;
  }
  if (! ssh_file_readaccess_ok(dir)) {
    if (ssh_mkdir(dir, 0700) < 0) {
      ssh_set_error(session, SSH_FATAL,
          "Cannot create %s directory.", dir);
      SAFE_FREE(dir);
      return -1;
    }
  }
  SAFE_FREE(dir);

  file = fopen(session->knownhosts, "a");
  if (file == NULL) {
    ssh_set_error(session, SSH_FATAL,
        "Couldn't open known_hosts file %s for appending: %s",
        session->knownhosts, strerror(errno));
    SAFE_FREE(host);
    return -1;
  }

  if (strcmp(session->current_crypto->server_pubkey_type, "ssh-rsa1") == 0) {
    /* openssh uses a different format for ssh-rsa1 keys.
       Be compatible --kv */
    ssh_public_key key;
    char *e_string = NULL;
    char *n_string = NULL;
    bignum e = NULL;
    bignum n = NULL;
    int rsa_size;
#ifdef HAVE_LIBGCRYPT
    gcry_sexp_t sexp;
#endif

    key = publickey_from_string(session, pubkey);
    if (key == NULL) {
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }

#ifdef HAVE_LIBGCRYPT
    sexp = gcry_sexp_find_token(key->rsa_pub, "e", 0);
    if (sexp == NULL) {
      publickey_free(key);
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }
    e = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
    gcry_sexp_release(sexp);
    if (e == NULL) {
      publickey_free(key);
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }

    sexp = gcry_sexp_find_token(key->rsa_pub, "n", 0);
    if (sexp == NULL) {
      publickey_free(key);
      bignum_free(e);
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }
    n = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG);
    gcry_sexp_release(sexp);
    if (n == NULL) {
      publickey_free(key);
      bignum_free(e);
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }

    rsa_size = (gcry_pk_get_nbits(key->rsa_pub) + 7) / 8;
#elif defined HAVE_LIBCRYPTO
    e = key->rsa_pub->e;
    n = key->rsa_pub->n;
    rsa_size = RSA_size(key->rsa_pub);
#endif

    e_string = bignum_bn2dec(e);
    n_string = bignum_bn2dec(n);
    if (e_string == NULL || n_string == NULL) {
#ifdef HAVE_LIBGCRYPT
      bignum_free(e);
      bignum_free(n);
      SAFE_FREE(e_string);
      SAFE_FREE(n_string);
#elif defined HAVE_LIBCRYPTO
      OPENSSL_free(e_string);
      OPENSSL_free(n_string);
#endif
      publickey_free(key);
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }

    snprintf(buffer, sizeof(buffer),
        "%s %d %s %s\n",
        host,
        rsa_size << 3,
        e_string,
        n_string);

#ifdef HAVE_LIBGCRYPT
    bignum_free(e);
    bignum_free(n);
    SAFE_FREE(e_string);
    SAFE_FREE(n_string);
#elif defined HAVE_LIBCRYPTO
    OPENSSL_free(e_string);
    OPENSSL_free(n_string);
#endif

    publickey_free(key);
  } else {
    pubkey_64 = bin_to_base64(pubkey->string, ssh_string_len(pubkey));
    if (pubkey_64 == NULL) {
      fclose(file);
      SAFE_FREE(host);
      return -1;
    }

    snprintf(buffer, sizeof(buffer),
        "%s %s %s\n",
        host,
        session->current_crypto->server_pubkey_type,
        pubkey_64);

    SAFE_FREE(pubkey_64);
  }
  SAFE_FREE(host);
  len = strlen(buffer);
  if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) {
    fclose(file);
    return -1;
  }

  fclose(file);
  return 0;
}
Пример #10
0
/* Authorize other end
 * Codes that tls_local_need and tls_remote_need can take:
 *
 *   BNET_TLS_NONE     I cannot do tls
 *   BNET_TLS_OK       I can do tls, but it is not required on my end
 *   BNET_TLS_REQUIRED  tls is required on my end
 *
 *   Returns: false if authentication failed
 *            true if OK
 */
bool cram_md5_challenge(BSOCK *bs, const char *password, int tls_local_need, bool compatible)
{
   struct timeval t1;
   struct timeval t2;
   struct timezone tz;
   int i;
   bool ok;
   char chal[MAXSTRING];
   char host[MAXSTRING];
   uint8_t hmac[20];

   gettimeofday(&t1, &tz);
   for (i=0; i<4; i++) {
      gettimeofday(&t2, &tz);
   }
   srandom((t1.tv_sec&0xffff) * (t2.tv_usec&0xff));
   if (!gethostname(host, sizeof(host))) {
      bstrncpy(host, my_name, sizeof(host));
   }
   /* Send challenge -- no hashing yet */
   bsnprintf(chal, sizeof(chal), "<%u.%u@%s>", (uint32_t)random(), (uint32_t)time(NULL), host);
   if (compatible) {
      Dmsg2(dbglvl, "send: auth cram-md5 %s ssl=%d\n", chal, tls_local_need);
      if (!bs->fsend("auth cram-md5 %s ssl=%d\n", chal, tls_local_need)) {
         Dmsg1(dbglvl, "Bnet send challenge comm error. ERR=%s\n", bs->bstrerror());
         return false;
      }
   } else {
      /* Old non-compatible system */
      Dmsg2(dbglvl, "send: auth cram-md5 %s ssl=%d\n", chal, tls_local_need);
      if (!bs->fsend("auth cram-md5 %s ssl=%d\n", chal, tls_local_need)) {
         Dmsg1(dbglvl, "Bnet send challenge comm error. ERR=%s\n", bs->bstrerror());
         return false;
      }
   }

   /* Read hashed response to challenge */
   if (bs->wait_data(180) <= 0 || bs->recv() <= 0) {
      Dmsg1(dbglvl, "Bnet receive challenge response comm error. ERR=%s\n", bs->bstrerror());
      bmicrosleep(5, 0);
      return false;
   }

   /* Attempt to duplicate hash with our password */
   hmac_md5((uint8_t *)chal, strlen(chal), (uint8_t *)password, strlen(password), hmac);
   bin_to_base64(host, sizeof(host), (char *)hmac, 16, compatible);
   ok = bstrcmp(bs->msg, host);
   if (ok) {
      Dmsg1(dbglvl, "Authenticate OK %s\n", host);
   } else {
      bin_to_base64(host, sizeof(host), (char *)hmac, 16, false);
      ok = bstrcmp(bs->msg, host);
      if (!ok) {
         Dmsg2(dbglvl, "Authenticate NOT OK: wanted %s, got %s\n", host, bs->msg);
      }
   }
   if (ok) {
      bs->fsend("1000 OK auth\n");
   } else {
      bs->fsend(_("1999 Authorization failed.\n"));
      bmicrosleep(5, 0);
   }
   return ok;
}
Пример #11
0
int main(int argc, char *const *argv)
{
    int retval = 0;
    int ch, kfd, length;
    bool base64_transform = false,
         clear_encryption = false,
         drive_encryption_status = false,
         generate_passphrase = false,
         populate_cache = false,
         set_encryption = false,
         show_keydata = false,
         volume_encryption_status = false,
         wrapped_keys = false;
    char *keyfile = NULL;
    char *cache_file = NULL;
    char *wrap_keyfile = NULL;
    char keydata[64];
    char wrapdata[64];

    setlocale(LC_ALL, "");
    bindtextdomain("bareos", LOCALEDIR);
    textdomain("bareos");

    while ((ch = getopt(argc, argv, "bcd:eg:k:p:s:vw:?")) != -1) {
        switch (ch) {
        case 'b':
            base64_transform = true;
            break;

        case 'c':
            clear_encryption = true;
            break;

        case 'd':
            debug_level = atoi(optarg);
            if (debug_level <= 0) {
                debug_level = 1;
            }
            break;

        case 'e':
            drive_encryption_status = true;
            break;

        case 'g':
            generate_passphrase = true;
            if (keyfile) {
                usage();
                goto bail_out;
            }
            keyfile = bstrdup(optarg);
            break;

        case 'k':
            show_keydata = true;
            if (keyfile) {
                usage();
                goto bail_out;
            }
            keyfile = bstrdup(optarg);
            break;

        case 'p':
            populate_cache = true;
            cache_file = bstrdup(optarg);
            break;

        case 's':
            set_encryption = true;
            if (keyfile) {
                usage();
                goto bail_out;
            }
            keyfile = bstrdup(optarg);
            break;

        case 'v':
            volume_encryption_status = true;
            break;

        case 'w':
            wrapped_keys = true;
            wrap_keyfile = bstrdup(optarg);
            break;

        case '?':
        default:
            usage();
            goto bail_out;

        }
    }

    argc -= optind;
    argv += optind;

    if (!generate_passphrase && !show_keydata && !populate_cache && argc < 1) {
        fprintf(stderr, _("Missing device_name argument for this option\n"));
        usage();
        retval = 1;
        goto bail_out;
    }

    if (generate_passphrase && show_keydata) {
        fprintf(stderr, _("Either use -g or -k not both\n"));
        retval = 1;
        goto bail_out;
    }

    if (clear_encryption && set_encryption) {
        fprintf(stderr, _("Either use -c or -s not both\n"));
        retval = 1;
        goto bail_out;
    }

    if ((clear_encryption ||
            set_encryption) &&
            (drive_encryption_status ||
             volume_encryption_status)) {
        fprintf(stderr, _("Either set or clear the crypto key or ask for status not both\n"));
        retval = 1;
        goto bail_out;
    }

    if ((clear_encryption ||
            set_encryption ||
            drive_encryption_status ||
            volume_encryption_status) &&
            (generate_passphrase ||
             show_keydata ||
             populate_cache)) {
        fprintf(stderr, _("Don't mix operations which are incompatible "
                          "e.g. generate/show vs set/clear etc.\n"));
        retval = 1;
        goto bail_out;
    }

    OSDependentInit();
    init_msg(NULL, NULL);

    if (populate_cache) {
        char *VolumeName, *EncrKey;
        char new_cache_entry[256];

        /*
         * Load any keys currently in the cache.
         */
        read_crypto_cache(cache_file);

        /*
         * Read new entries from stdin and parse them to update
         * the cache.
         */
        fprintf(stdout, _("Enter cache entrie(s) (close with ^D): "));
        fflush(stdout);
        while (read(1, new_cache_entry, sizeof(new_cache_entry)) > 0) {
            strip_trailing_junk(new_cache_entry);

            /*
             * Try to parse the entry.
             */
            VolumeName = new_cache_entry;
            EncrKey = strchr(new_cache_entry, '\t');
            if (!EncrKey) {
                break;
            }

            *EncrKey++ = '\0';
            update_crypto_cache(VolumeName, EncrKey);
        }

        /*
         * Write out the new cache entries.
         */
        write_crypto_cache(cache_file);
        goto bail_out;
    }

    memset(keydata, 0, sizeof(keydata));
    memset(wrapdata, 0, sizeof(wrapdata));

    if (wrapped_keys) {
        /*
         * Read the key bits from the keyfile.
         * - == stdin
         */
        if (bstrcmp(wrap_keyfile, "-")) {
            kfd = 0;
            fprintf(stdout, _("Enter Key Encryption Key: "));
            fflush(stdout);
        } else {
            kfd = open(wrap_keyfile, O_RDONLY);
            if (kfd < 0) {
                fprintf(stderr, _("Cannot open keyfile %s\n"), wrap_keyfile);
                retval = 1;
                goto bail_out;
            }
        }
        read(kfd, wrapdata, sizeof(wrapdata));
        if (kfd > 0) {
            close(kfd);
        }
        strip_trailing_junk(wrapdata);
        Dmsg1(10, "Wrapped keydata = %s\n", wrapdata);
    }

    /*
     * Generate a new passphrase allow it to be wrapped using the given wrapkey
     * and base64 if specified or when wrapped.
     */
    if (generate_passphrase) {
        int cnt;
        char *passphrase;

        passphrase = generate_crypto_passphrase(DEFAULT_PASSPHRASE_LENGTH);
        if (!passphrase) {
            retval = 1;
            goto bail_out;
        }

        Dmsg1(10, "Generated passphrase = %s\n", passphrase);

        /*
         * See if we need to wrap the passphrase.
         */
        if (wrapped_keys) {
            char *wrapped_passphrase;

            length = DEFAULT_PASSPHRASE_LENGTH + 8;
            wrapped_passphrase = (char *)malloc(length);
            memset(wrapped_passphrase, 0, length);
            aes_wrap((unsigned char *)wrapdata,
                     DEFAULT_PASSPHRASE_LENGTH / 8,
                     (unsigned char *)passphrase,
                     (unsigned char *)wrapped_passphrase);

            free(passphrase);
            passphrase = wrapped_passphrase;
        } else {
            length = DEFAULT_PASSPHRASE_LENGTH;
        }

        /*
         * See where to write the key.
         * - == stdout
         */
        if (bstrcmp(keyfile, "-")) {
            kfd = 1;
        } else {
            kfd = open(keyfile, O_WRONLY | O_CREAT, 0644);
            if (kfd < 0) {
                fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile);
                free(passphrase);
                retval = 1;
                goto bail_out;
            }
        }

        if (base64_transform || wrapped_keys) {
            cnt = bin_to_base64(keydata, sizeof(keydata), passphrase, length, true);
            if (write(kfd, keydata, cnt) != cnt) {
                fprintf(stderr, _("Failed to write %d bytes to keyfile %s\n"), cnt, keyfile);
            }
        } else {
            cnt = DEFAULT_PASSPHRASE_LENGTH;
            if (write(kfd, passphrase, cnt) != cnt) {
                fprintf(stderr, _("Failed to write %d bytes to keyfile %s\n"), cnt, keyfile);
            }
        }

        Dmsg1(10, "Keydata = %s\n", keydata);

        if (kfd > 1) {
            close(kfd);
        } else {
            write(kfd, "\n", 1);
        }
        free(passphrase);
        goto bail_out;
    }

    if (show_keydata) {
        char *passphrase;

        /*
         * Read the key bits from the keyfile.
         * - == stdin
         */
        if (bstrcmp(keyfile, "-")) {
            kfd = 0;
            fprintf(stdout, _("Enter Encryption Key: "));
            fflush(stdout);
        } else {
            kfd = open(keyfile, O_RDONLY);
            if (kfd < 0) {
                fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile);
                retval = 1;
                goto bail_out;
            }
        }
        read(kfd, keydata, sizeof(keydata));
        if (kfd > 0) {
            close(kfd);
        }
        strip_trailing_junk(keydata);
        Dmsg1(10, "Keydata = %s\n", keydata);

        /*
         * See if we need to unwrap the passphrase.
         */
        if (wrapped_keys) {
            char *wrapped_passphrase;
            /*
             * A wrapped key is base64 encoded after it was wrapped so first
             * convert it from base64 to bin. As we first go from base64 to bin
             * and the base64_to_bin has a check if the decoded string will fit
             * we need to alocate some more bytes for the decoded buffer to be
             * sure it will fit.
             */
            length = DEFAULT_PASSPHRASE_LENGTH + 12;
            wrapped_passphrase = (char *)malloc(length);
            memset(wrapped_passphrase, 0, length);
            if (base64_to_bin(wrapped_passphrase, length,
                              keydata, strlen(keydata)) == 0) {
                fprintf(stderr,
                        _("Failed to base64 decode the keydata read from %s, aborting...\n"),
                        keyfile);
                free(wrapped_passphrase);
                goto bail_out;
            }

            length = DEFAULT_PASSPHRASE_LENGTH;
            passphrase = (char *)malloc(length);
            memset(passphrase, 0, length);

            if (aes_unwrap((unsigned char *)wrapdata,
                           length / 8,
                           (unsigned char *)wrapped_passphrase,
                           (unsigned char *)passphrase) == -1) {
                fprintf(stderr,
                        _("Failed to aes unwrap the keydata read from %s using the wrap data from %s, aborting...\n"),
                        keyfile, wrap_keyfile);
                free(wrapped_passphrase);
                goto bail_out;
            }

            free(wrapped_passphrase);
        } else {
            if (base64_transform) {
                /*
                 * As we first go from base64 to bin and the base64_to_bin has a check
                 * if the decoded string will fit we need to alocate some more bytes
                 * for the decoded buffer to be sure it will fit.
                 */
                length = DEFAULT_PASSPHRASE_LENGTH + 4;
                passphrase = (char *)malloc(length);
                memset(passphrase, 0, length);

                base64_to_bin(passphrase, length, keydata, strlen(keydata));
            } else {
                length = DEFAULT_PASSPHRASE_LENGTH;
                passphrase = (char *)malloc(length);
                memset(passphrase, 0, length);
                bstrncpy(passphrase, keydata, length);
            }
        }

        Dmsg1(10, "Unwrapped passphrase = %s\n", passphrase);
        fprintf(stdout, "%s\n", passphrase);

        free(passphrase);
        goto bail_out;
    }

    /*
     * Clear the loaded encryption key of the given drive.
     */
    if (clear_encryption) {
        if (clear_scsi_encryption_key(-1, argv[0])) {
            goto bail_out;
        } else {
            retval = 1;
            goto bail_out;
        }
    }

    /*
     * Get the drive encryption status of the given drive.
     */
    if (drive_encryption_status) {
        POOLMEM *encryption_status = get_pool_memory(PM_MESSAGE);

        if (get_scsi_drive_encryption_status(-1, argv[0], encryption_status, 0)) {
            fprintf(stdout, "%s", encryption_status);
            free_pool_memory(encryption_status);
        } else {
            retval = 1;
            free_pool_memory(encryption_status);
            goto bail_out;
        }
    }

    /*
     * Load a new encryption key onto the given drive.
     */
    if (set_encryption) {
        /*
         * Read the key bits from the keyfile.
         * - == stdin
         */
        if (bstrcmp(keyfile, "-")) {
            kfd = 0;
            fprintf(stdout, _("Enter Encryption Key (close with ^D): "));
            fflush(stdout);
        } else {
            kfd = open(keyfile, O_RDONLY);
            if (kfd < 0) {
                fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile);
                retval = 1;
                goto bail_out;
            }
        }
        read(kfd, keydata, sizeof(keydata));
        if (kfd > 0) {
            close(kfd);
        }
        strip_trailing_junk(keydata);

        if (set_scsi_encryption_key(-1, argv[0], keydata)) {
            goto bail_out;
        } else {
            retval = 1;
            goto bail_out;
        }
    }

    /*
     * Get the volume encryption status of volume currently loaded in the given drive.
     */
    if (volume_encryption_status) {
        POOLMEM *encryption_status = get_pool_memory(PM_MESSAGE);

        if (get_scsi_volume_encryption_status(-1, argv[0], encryption_status, 0)) {
            fprintf(stdout, "%s", encryption_status);
            free_pool_memory(encryption_status);
        } else {
            retval = 1;
            free_pool_memory(encryption_status);
            goto bail_out;
        }
    }

bail_out:
    if (cache_file) {
        free(cache_file);
    }

    if (keyfile) {
        free(keyfile);
    }

    if (wrap_keyfile) {
        free(wrap_keyfile);
    }

    exit(retval);
}
Пример #12
0
/* This function is a modified version of the one found in bacula in src/lib/cram-md5.c */
int authenticate_monitor(monitor * mon)
{   
   char hello[] = "Hello *UserAgent* calling\n";
   int tls, compatible, err;
      
   /* Send the initial hello message */
   err = send_message(mon, hello, strlen(hello));
   if(err != E_SUCCESS) {
      return err;
   }

   /* Get the cram challenge and respond */
   {
      char resp[MAXSTRING];
      char chal[MAXSTRING];
      char msg[MAXSTRING];
      uint8_t hmac[20];
      size_t len;

      err = receive_message(mon, resp, MAXSTRING);
      if(err < E_SUCCESS) {
         return err;
      }

      compatible = 0;
      if(sscanf(resp, "auth cram-md5c %s ssl=%d", chal, &tls) == 2) {
         compatible = 1;
      } else if(sscanf(resp, "auth cram-md5 %s ssl=%d", chal, &tls) != 2) {
         if(sscanf(resp, "auth cram-md5 %s\n", chal) != 1) {
            return E_MONITOR_BAD_SCAN_CHALLENGE;
         }
      }

      hmac_md5((uint8_t *)chal, strlen(chal), (uint8_t *)mon->passwd, strlen(mon->passwd), hmac);
      len = bin_to_base64(msg, 50, (char *)hmac, 16, compatible) + 1;
      
      err = send_message(mon, msg, len);
      if(err != E_SUCCESS) {
         return err;
      }

      err = receive_message(mon, resp, MAXSTRING);
      if(err < E_SUCCESS) {
         return err;
      }
      
      if(strcmp(resp, "1000 OK auth\n") != 0) {
         return E_MONITOR_AUTH_FAILED;
      }
   }

   /* send our cram challenge */
   {
      int i;
      struct timeval t1;
      struct timeval t2;
      struct timezone tz;
      char chal[MAXSTRING];
   
      gettimeofday(&t1, &tz);
      for(i = 0; i < 4; ++i) {
         gettimeofday(&t2, &tz);
      }

      srandom((t1.tv_sec&0xffff) * (t2.tv_usec&0xff));
      snprintf(chal, sizeof(chal), "auth cram-md5 <%u.%u@%s> ssl=0\n", 
               (uint32_t)random(), (uint32_t)time(NULL), mon->host_name);
   }

/*   err = receive_message(mon, resp, MAXSTRING);
   if(err != E_SUCCESS) {
      return err;
   }
*/
   return E_SUCCESS;
}
Пример #13
0
/*
 * Called here by find() for each file.
 *
 *  Find the file, compute the MD5 or SHA1 and send it back to the Director
 */
static int verify_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
{
   POOL_MEM attribs(PM_NAME),
            attribsEx(PM_NAME);
   int digest_stream = STREAM_NONE;
   int status;
   DIGEST *digest = NULL;
   BSOCK *dir;

   if (job_canceled(jcr)) {
      return 0;
   }

   dir = jcr->dir_bsock;
   jcr->num_files_examined++;         /* bump total file count */

   switch (ff_pkt->type) {
   case FT_LNKSAVED:                  /* Hard linked, file already saved */
      Dmsg2(30, "FT_LNKSAVED saving: %s => %s\n", ff_pkt->fname, ff_pkt->link);
      break;
   case FT_REGE:
      Dmsg1(30, "FT_REGE saving: %s\n", ff_pkt->fname);
      break;
   case FT_REG:
      Dmsg1(30, "FT_REG saving: %s\n", ff_pkt->fname);
      break;
   case FT_LNK:
      Dmsg2(30, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link);
      break;
   case FT_DIRBEGIN:
      jcr->num_files_examined--;      /* correct file count */
      return 1;                       /* ignored */
   case FT_REPARSE:
   case FT_JUNCTION:
   case FT_DIREND:
      Dmsg1(30, "FT_DIR saving: %s\n", ff_pkt->fname);
      break;
   case FT_SPEC:
      Dmsg1(30, "FT_SPEC saving: %s\n", ff_pkt->fname);
      break;
   case FT_RAW:
      Dmsg1(30, "FT_RAW saving: %s\n", ff_pkt->fname);
      break;
   case FT_FIFO:
      Dmsg1(30, "FT_FIFO saving: %s\n", ff_pkt->fname);
      break;
   case FT_NOACCESS: {
      berrno be;
      be.set_errno(ff_pkt->ff_errno);
      Jmsg(jcr, M_NOTSAVED, 1, _("     Could not access %s: ERR=%s\n"), ff_pkt->fname, be.bstrerror());
      jcr->JobErrors++;
      return 1;
   }
   case FT_NOFOLLOW: {
      berrno be;
      be.set_errno(ff_pkt->ff_errno);
      Jmsg(jcr, M_NOTSAVED, 1, _("     Could not follow link %s: ERR=%s\n"), ff_pkt->fname, be.bstrerror());
      jcr->JobErrors++;
      return 1;
   }
   case FT_NOSTAT: {
      berrno be;
      be.set_errno(ff_pkt->ff_errno);
      Jmsg(jcr, M_NOTSAVED, 1, _("     Could not stat %s: ERR=%s\n"), ff_pkt->fname, be.bstrerror());
      jcr->JobErrors++;
      return 1;
   }
   case FT_DIRNOCHG:
   case FT_NOCHG:
      Jmsg(jcr, M_SKIPPED, 1, _("     Unchanged file skipped: %s\n"), ff_pkt->fname);
      return 1;
   case FT_ISARCH:
      Jmsg(jcr, M_SKIPPED, 1, _("     Archive file skipped: %s\n"), ff_pkt->fname);
      return 1;
   case FT_NORECURSE:
      Jmsg(jcr, M_SKIPPED, 1, _("     Recursion turned off. Directory skipped: %s\n"), ff_pkt->fname);
      ff_pkt->type = FT_DIREND;     /* directory entry was backed up */
      break;
   case FT_NOFSCHG:
      Jmsg(jcr, M_SKIPPED, 1, _("     File system change prohibited. Directory skipped: %s\n"), ff_pkt->fname);
      return 1;
   case FT_PLUGIN_CONFIG:
   case FT_RESTORE_FIRST:
      return 1;                       /* silently skip */
   case FT_NOOPEN: {
      berrno be;
      be.set_errno(ff_pkt->ff_errno);
      Jmsg(jcr, M_NOTSAVED, 1, _("     Could not open directory %s: ERR=%s\n"), ff_pkt->fname, be.bstrerror());
      jcr->JobErrors++;
      return 1;
   }
   default:
      Jmsg(jcr, M_NOTSAVED, 0, _("     Unknown file type %d: %s\n"), ff_pkt->type, ff_pkt->fname);
      jcr->JobErrors++;
      return 1;
   }

   /* Encode attributes and possibly extend them */
   encode_stat(attribs.c_str(), &ff_pkt->statp, sizeof(ff_pkt->statp), ff_pkt->LinkFI, 0);
   encode_attribsEx(jcr, attribsEx.c_str(), ff_pkt);

   jcr->lock();
   jcr->JobFiles++;                  /* increment number of files sent */
   pm_strcpy(jcr->last_fname, ff_pkt->fname);
   jcr->unlock();

   /*
    * Send file attributes to Director
    *   File_index
    *   Stream
    *   Verify Options
    *   Filename (full path)
    *   Encoded attributes
    *   Link name (if type==FT_LNK)
    * For a directory, link is the same as fname, but with trailing
    * slash. For a linked file, link is the link.
    */
   /* Send file attributes to Director (note different format than for Storage) */
   Dmsg2(400, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, ff_pkt->fname);
   if (ff_pkt->type == FT_LNK || ff_pkt->type == FT_LNKSAVED) {
      status = dir->fsend("%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
                          STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname,
                          0, attribs.c_str(), 0, ff_pkt->link, 0);
   } else if (ff_pkt->type == FT_DIREND || ff_pkt->type == FT_REPARSE ||
              ff_pkt->type == FT_JUNCTION) {
      /* Here link is the canonical filename (i.e. with trailing slash) */
      status = dir->fsend("%d %d %s %s%c%s%c%c", jcr->JobFiles,
                          STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->link,
                          0, attribs.c_str(), 0, 0);
   } else {
      status = dir->fsend("%d %d %s %s%c%s%c%c", jcr->JobFiles,
                          STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname,
                          0, attribs.c_str(), 0, 0);
   }
   Dmsg2(20, "filed>dir: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
   if (!status) {
      Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
      return 0;
   }

   /*
    * The remainder of the function is all about getting the checksum.
    * First we initialise, then we read files, other streams and Finder Info.
    */
   if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
            ff_pkt->flags & (FO_MD5|FO_SHA1|FO_SHA256|FO_SHA512))) {
      /*
       * Create our digest context. If this fails, the digest will be set to NULL
       * and not used.
       */
      if (ff_pkt->flags & FO_MD5) {
         digest = crypto_digest_new(jcr, CRYPTO_DIGEST_MD5);
         digest_stream = STREAM_MD5_DIGEST;

      } else if (ff_pkt->flags & FO_SHA1) {
         digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA1);
         digest_stream = STREAM_SHA1_DIGEST;

      } else if (ff_pkt->flags & FO_SHA256) {
         digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA256);
         digest_stream = STREAM_SHA256_DIGEST;

      } else if (ff_pkt->flags & FO_SHA512) {
         digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA512);
         digest_stream = STREAM_SHA512_DIGEST;
      }

      /* Did digest initialization fail? */
      if (digest_stream != STREAM_NONE && digest == NULL) {
         Jmsg(jcr, M_WARNING, 0, _("%s digest initialization failed\n"),
              stream_to_ascii(digest_stream));
      }

      /* compute MD5 or SHA1 hash */
      if (digest) {
         char md[CRYPTO_DIGEST_MAX_SIZE];
         uint32_t size;

         size = sizeof(md);

         if (digest_file(jcr, ff_pkt, digest) != 0) {
            jcr->JobErrors++;
            goto good_rtn;
         }

         if (crypto_digest_finalize(digest, (uint8_t *)md, &size)) {
            char *digest_buf;
            const char *digest_name;

            digest_buf = (char *)malloc(BASE64_SIZE(size));
            digest_name = crypto_digest_name(digest);

            bin_to_base64(digest_buf, BASE64_SIZE(size), md, size, true);
            Dmsg3(400, "send inx=%d %s=%s\n", jcr->JobFiles, digest_name, digest_buf);
            dir->fsend("%d %d %s *%s-%d*", jcr->JobFiles, digest_stream, digest_buf,
                       digest_name, jcr->JobFiles);
            Dmsg3(20, "filed>dir: %s len=%d: msg=%s\n", digest_name,
                  dir->msglen, dir->msg);

            free(digest_buf);
         }
      }
   }

good_rtn:
   if (digest) {
      crypto_digest_free(digest);
   }
   return 1;
}
Пример #14
0
ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
                                          const char *passphrase,
                                          ssh_auth_callback auth_fn,
                                          void *auth_data)
{
    ssh_buffer buffer;
    ssh_string str = NULL;
    ssh_string pubkey_s=NULL;
    ssh_buffer privkey_buffer = NULL;
    uint32_t rnd;
    uint32_t rounds = 16;
    ssh_string salt=NULL;
    ssh_string kdf_options=NULL;
    int to_encrypt=0;
    unsigned char *b64;
    uint32_t str_len, len;
    int rc;

    if (privkey == NULL) {
        return NULL;
    }
    if (privkey->type != SSH_KEYTYPE_ED25519){
        ssh_pki_log("Unsupported key type %s", privkey->type_c);
        return NULL;
    }
    if (passphrase != NULL || auth_fn != NULL){
        ssh_pki_log("Enabling encryption for private key export");
        to_encrypt = 1;
    }
    buffer = ssh_buffer_new();
    pubkey_s = pki_publickey_to_blob(privkey);
    if(buffer == NULL || pubkey_s == NULL){
        goto error;
    }
    ssh_get_random(&rnd, sizeof(rnd), 0);

    privkey_buffer = ssh_buffer_new();
    if (privkey_buffer == NULL) {
        goto error;
    }

    /* checkint1 & 2 */
    rc = ssh_buffer_pack(privkey_buffer,
                         "dd",
                         rnd,
                         rnd);
    if (rc == SSH_ERROR){
        goto error;
    }

    rc = pki_openssh_export_privkey_blob(privkey, privkey_buffer);
    if (rc == SSH_ERROR){
        goto error;
    }

    /* comment */
    rc = ssh_buffer_pack(privkey_buffer, "s", "" /* comment */);
    if (rc == SSH_ERROR){
        goto error;
    }

    if (to_encrypt){
        ssh_buffer kdf_buf;

        kdf_buf = ssh_buffer_new();
        if (kdf_buf == NULL) {
            goto error;
        }

        salt = ssh_string_new(16);
        if (salt == NULL){
            ssh_buffer_free(kdf_buf);
            goto error;
        }
        ssh_get_random(ssh_string_data(salt),16, 0);
        ssh_buffer_pack(kdf_buf, "Sd", salt, rounds);
        kdf_options = ssh_string_new(ssh_buffer_get_len(kdf_buf));
        if (kdf_options == NULL){
            ssh_buffer_free(kdf_buf);
            goto error;
        }
        memcpy(ssh_string_data(kdf_options),
               ssh_buffer_get_begin(kdf_buf),
               ssh_buffer_get_len(kdf_buf));
        ssh_buffer_free(kdf_buf);
        rc = pki_private_key_encrypt(privkey_buffer,
                                     passphrase,
                                     "aes128-cbc",
                                     "bcrypt",
                                     auth_fn,
                                     auth_data,
                                     rounds,
                                     salt);
        if (rc != SSH_OK){
            goto error;
        }
    } else {
        kdf_options = ssh_string_new(0);
    }

    rc = ssh_buffer_pack(buffer,
                         "PssSdSdP",
                         (size_t)strlen(OPENSSH_AUTH_MAGIC) + 1, OPENSSH_AUTH_MAGIC,
                         to_encrypt ? "aes128-cbc" : "none", /* ciphername */
                         to_encrypt ? "bcrypt" : "none", /* kdfname */
                         kdf_options, /* kdfoptions */
                         (uint32_t) 1, /* nkeys */
                         pubkey_s,
                         (uint32_t)ssh_buffer_get_len(privkey_buffer),
                         /* rest of buffer is a string */
                         (size_t)ssh_buffer_get_len(privkey_buffer), ssh_buffer_get_begin(privkey_buffer));
    if (rc != SSH_OK) {
        goto error;
    }

    b64 = bin_to_base64(ssh_buffer_get_begin(buffer),
                        ssh_buffer_get_len(buffer));
    if (b64 == NULL){
        goto error;
    }

    /* we can reuse the buffer */
    ssh_buffer_reinit(buffer);
    rc = ssh_buffer_pack(buffer,
                         "tttttt",
                         OPENSSH_HEADER_BEGIN,
                         "\n",
                         b64,
                         "\n",
                         OPENSSH_HEADER_END,
                         "\n");
    BURN_BUFFER(b64, strlen((char *)b64));
    SAFE_FREE(b64);

    if (rc != SSH_OK){
        goto error;
    }

    str = ssh_string_new(ssh_buffer_get_len(buffer));
    if (str == NULL){
        goto error;
    }

    str_len = ssh_buffer_get_len(buffer);
    len = buffer_get_data(buffer, ssh_string_data(str), str_len);
    if (str_len != len) {
        ssh_string_free(str);
        str = NULL;
    }

error:
    if (privkey_buffer != NULL) {
        void *bufptr = ssh_buffer_get_begin(privkey_buffer);
        BURN_BUFFER(bufptr, ssh_buffer_get_len(privkey_buffer));
        ssh_buffer_free(privkey_buffer);
    }
    SAFE_FREE(pubkey_s);
    SAFE_FREE(kdf_options);
    SAFE_FREE(salt);
    if (buffer != NULL) {
        ssh_buffer_free(buffer);
    }

    return str;
}
Пример #15
0
void test_base64(void **state) {
   (void) state; /* unused */


/*
 * Test the base64 routines by encoding and decoding
 * lstat() packets.
 */

   char where[500];
   int i;
   char *fname;
   struct stat statp;
   struct stat statn;
   int debug_level = 0;
   char *p;
   int32_t j;
   time_t t = 1028712799;


   fname = BINARYNAME;
   base64_init();
   if (lstat(fname, &statp) < 0) {
      berrno be;
      printf("Cannot stat %s: %s\n", fname, be.bstrerror(errno));
   }
   encode_stat(where, &statp, sizeof(statp), 0, 0);

   //printf("Encoded stat=%s\n", where);

#ifdef xxx
   p = where;
   p += to_base64((int64_t)(statp.st_atime), p);
   *p++ = ' ';
   p += to_base64((int64_t)t, p);
   printf("%s %s\n", fname, where);

   printf("%s %lld\n", "st_dev", (int64_t)statp.st_dev);
   printf("%s %lld\n", "st_ino", (int64_t)statp.st_ino);
   printf("%s %lld\n", "st_mode", (int64_t)statp.st_mode);
   printf("%s %lld\n", "st_nlink", (int64_t)statp.st_nlink);
   printf("%s %lld\n", "st_uid", (int64_t)statp.st_uid);
   printf("%s %lld\n", "st_gid", (int64_t)statp.st_gid);
   printf("%s %lld\n", "st_rdev", (int64_t)statp.st_rdev);
   printf("%s %lld\n", "st_size", (int64_t)statp.st_size);
   printf("%s %lld\n", "st_blksize", (int64_t)statp.st_blksize);
   printf("%s %lld\n", "st_blocks", (int64_t)statp.st_blocks);
   printf("%s %lld\n", "st_atime", (int64_t)statp.st_atime);
   printf("%s %lld\n", "st_mtime", (int64_t)statp.st_mtime);
   printf("%s %lld\n", "st_ctime", (int64_t)statp.st_ctime);
#endif

   //printf("%s: len=%d val=%s\n", fname, strlen(where), where);

   decode_stat(where, &statn, sizeof(statn), &j);

   assert_false(statp.st_dev != statn.st_dev ||
         statp.st_ino != statn.st_ino ||
         statp.st_mode != statn.st_mode ||
         statp.st_nlink != statn.st_nlink ||
         statp.st_uid != statn.st_uid ||
         statp.st_gid != statn.st_gid ||
         statp.st_rdev != statn.st_rdev ||
         statp.st_size != statn.st_size ||
         statp.st_blksize != statn.st_blksize ||
         statp.st_blocks != statn.st_blocks ||
         statp.st_atime != statn.st_atime ||
         statp.st_mtime != statn.st_mtime ||
         statp.st_ctime != statn.st_ctime);

   /*
      {  printf("%s: %s\n", fname, where);
      encode_stat(where, &statn, sizeof(statn), 0, 0);
      printf("%s: %s\n", fname, where);
      printf("NOT EQAL\n");
      }
      */


//printf("%d files examined\n", i);

to_base64(UINT32_MAX, where);
//printf("UINT32_MAX=%s\n", where);











int xx = 0;
int len;
char buf[100];
char junk[100];
//   int i;

#ifdef xxxx
   for (i=0; i < 1000; i++) {
      bin_to_base64(buf, sizeof(buf), (char *)&xx, 4, true);
      printf("xx=%s\n", buf);
      xx++;
   }
#endif
   junk[0] = 0xFF;
   for (i=1; i<100; i++) {
      junk[i] = junk[i-1]-1;
   }
   len = bin_to_base64(buf, sizeof(buf), junk, 16, true);
   //printf("len=%d junk=%s\n", len, buf);

   strcpy(junk, "This is a sample string");
   len = bin_to_base64(buf, sizeof(buf), junk, strlen(junk), true);
   buf[len] = 0;
   base64_to_bin(junk, sizeof(junk), buf, len);
   //printf("buf=<%s>\n", junk);

}