Ejemplo n.º 1
0
/****************
 * This function may be used for the Content-Type header to figure out
 * the media type and subtype.  Note, that the returned strings are
 * guaranteed to be lowercase as required by MIME.
 *
 * Returns: a pointer to the media type and if subtype is not NULL,
 *	    a pointer to the subtype.
 */
const char *
rfc822parse_query_media_type (rfc822parse_field_t ctx, const char **subtype)
{
  TOKEN t = ctx;
  const char *type;

  if (t->type != tATOM)
    return NULL;
  if (!t->flags.lowered)
    {
      lowercase_string (t->data);
      t->flags.lowered = 1;
    }
  type = t->data;
  t = t->next;
  if (!t || t->type != tSPECIAL || t->data[0] != '/')
    return NULL;
  t = t->next;
  if (!t || t->type != tATOM)
    return NULL;

  if (subtype)
    {
      if (!t->flags.lowered)
        {
          lowercase_string (t->data);
          t->flags.lowered = 1;
        }
      *subtype = t->data;
    }
  return type;
}
Ejemplo n.º 2
0
/*
   Some header (Content-type) have a special syntax where attribute=value
   pairs are used after a leading semicolon.  The parse_field code
   knows about these fields and changes the parsing to the one defined
   in RFC2045.
   Returns a pointer to the value which is valid as long as the
   parse context is valid; NULL is returned in case that attr is not
   defined in the header, a missing value is represented by an empty string.

   With LOWER_VALUE set to true, a matching field value will be
   lowercased.

   Note, that ATTR should be lowercase.  If ATTR is NULL the fucntion
   returns the first token of the field; i.e. not the parameter but
   the actual value.  A CTX of NULL is allowed and will return NULL.
 */
const char *
rfc822parse_query_parameter (rfc822parse_field_t ctx, const char *attr,
                             int lower_value)
{
  TOKEN t, a;

  if (!attr)
    {
      t = ctx;
      if (t
          && (t->type == tATOM || t->type == tQUOTED || t->type == tDOMAINLIT))
        {
          if ( lower_value && !t->flags.lowered )
            {
              lowercase_string (t->data);
              t->flags.lowered = 1;
            }
          return t->data;
        }
      return NULL;
    }

  for (t = ctx; t; t = t->next)
    {
      /* skip to the next semicolon */
      for (; t && !(t->type == tSPECIAL && t->data[0] == ';'); t = t->next)
	;
      if (!t)
	return NULL;
      if (is_parameter (t))
	{ /* Look closer. */
	  a = t->next; /* We know that this is an atom */
          if ( !a->flags.lowered )
            {
              lowercase_string (a->data);
              a->flags.lowered = 1;
            }
	  if (!strcmp (a->data, attr))
	    { /* found */
	      t = a->next->next;
	      /* Either T is now an atom, a quoted string or NULL in
	       * which case we return an empty string. */

              if ( lower_value && t && !t->flags.lowered )
                {
                  lowercase_string (t->data);
                  t->flags.lowered = 1;
                }
	      return t ? t->data : "";
	    }
	}
    }
  return NULL;
}
int main(void)
{
   char s[] = "HOLBERTON SCHOOL!!\n";
   char *p;

   p = lowercase_string(s);
   printf("%s", p);
   printf("%s", s);
   return (0);
}
int main(void)
{
   char s[] = "Holberton School!\n";
   char *p;

   p = lowercase_string(s);
   printf("%s", p);
   printf("%s", s);
   return (0);
}
Ejemplo n.º 5
0
int main(const int argc, char *const argv[])
{
	struct cifs_spnego_msg *keydata = NULL;
	DATA_BLOB secblob = data_blob_null;
	DATA_BLOB sess_key = data_blob_null;
	key_serial_t key = 0;
	size_t datalen;
	unsigned int have;
	long rc = 1;
	int c, try_dns = 0, legacy_uid = 0;
	char *buf, *ccdir = NULL, *ccname = NULL, *best_cache = NULL;
	char hostbuf[NI_MAXHOST], *host;
	struct decoded_args arg;
	const char *oid;
	uid_t uid;
	char *keytab_name = CIFS_DEFAULT_KRB5_KEYTAB;
	time_t best_time = 0;

	hostbuf[0] = '\0';
	memset(&arg, 0, sizeof(arg));

	openlog(prog, 0, LOG_DAEMON);

	while ((c = getopt_long(argc, argv, "ck:ltv", long_options, NULL)) != -1) {
		switch (c) {
		case 'c':
			/* legacy option -- skip it */
			break;
		case 't':
			try_dns++;
			break;
		case 'k':
			if (setenv("KRB5_CONFIG", optarg, 1) != 0) {
				syslog(LOG_ERR, "unable to set $KRB5_CONFIG: %d", errno);
				goto out;
			}
			break;
		case 'l':
			legacy_uid++;
			break;
		case 'v':
			printf("version: %s\n", VERSION);
			goto out;
		default:
			syslog(LOG_ERR, "unknown option: %c", c);
			goto out;
		}
	}

	/* is there a key? */
	if (argc <= optind) {
		usage();
		goto out;
	}

	/* get key and keyring values */
	errno = 0;
	key = strtol(argv[optind], NULL, 10);
	if (errno != 0) {
		key = 0;
		syslog(LOG_ERR, "Invalid key format: %s", strerror(errno));
		goto out;
	}

	rc = keyctl_describe_alloc(key, &buf);
	if (rc == -1) {
		syslog(LOG_ERR, "keyctl_describe_alloc failed: %s",
		       strerror(errno));
		rc = 1;
		goto out;
	}

	syslog(LOG_DEBUG, "key description: %s", buf);

	if ((strncmp(buf, "cifs.resolver", sizeof("cifs.resolver") - 1) == 0) ||
	    (strncmp(buf, "dns_resolver", sizeof("dns_resolver") - 1) == 0)) {
		rc = cifs_resolver(key, buf);
		goto out;
	}

	have = decode_key_description(buf, &arg);
	SAFE_FREE(buf);
	if ((have & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) {
		syslog(LOG_ERR, "unable to get necessary params from key "
		       "description (0x%x)", have);
		rc = 1;
		goto out;
	}

	if (arg.ver > CIFS_SPNEGO_UPCALL_VERSION) {
		syslog(LOG_ERR, "incompatible kernel upcall version: 0x%x",
		       arg.ver);
		rc = 1;
		goto out;
	}

	if (strlen(arg.hostname) >= NI_MAXHOST) {
		syslog(LOG_ERR, "hostname provided by kernel is too long");
		rc = 1;
		goto out;

	}

	if (!legacy_uid && (have & DKD_HAVE_CREDUID))
		uid = arg.creduid;
	else if (have & DKD_HAVE_UID)
		uid = arg.uid;
	else {
		/* no uid= or creduid= parm -- something is wrong */
		syslog(LOG_ERR, "No uid= or creduid= parm specified");
		rc = 1;
		goto out;
	}

	rc = setuid(uid);
	if (rc == -1) {
		syslog(LOG_ERR, "setuid: %s", strerror(errno));
		goto out;
	}
	ccdir = resolve_krb5_dir(CIFS_DEFAULT_KRB5_USER_DIR, uid);
	if (ccdir != NULL)
		find_krb5_cc(ccdir, uid, &best_cache, &best_time);
	ccname = find_krb5_cc(CIFS_DEFAULT_KRB5_DIR, uid, &best_cache,
			      &best_time);
	SAFE_FREE(ccdir);

	/* Couldn't find credcache? Try to use keytab */
	if (ccname == NULL && arg.username != NULL)
		ccname = init_cc_from_keytab(keytab_name, arg.username);

	host = arg.hostname;

	// do mech specific authorization
	switch (arg.sec) {
	case MS_KRB5:
	case KRB5:
		/*
		 * Andrew Bartlett's suggested scheme for picking a principal
		 * name, based on a supplied hostname.
		 *
		 * INPUT: fooo
		 * TRY in order:
		 * cifs/fooo@REALM
		 * cifs/fooo.<guessed domain ?>@REALM
		 *
		 * INPUT: bar.example.com
		 * TRY only:
		 * cifs/bar.example.com@REALM
		 */
		if (arg.sec == MS_KRB5)
			oid = OID_KERBEROS5_OLD;
		else
			oid = OID_KERBEROS5;

retry_new_hostname:
		lowercase_string(host);
		rc = handle_krb5_mech(oid, host, &secblob, &sess_key, ccname);
		if (!rc)
			break;

		/*
		 * If hostname has a '.', assume it's a FQDN, otherwise we
		 * want to guess the domainname.
		 */
		if (!strchr(host, '.')) {
			struct addrinfo hints;
			struct addrinfo *ai;
			char *domainname;
			char fqdn[NI_MAXHOST];

			/*
			 * use getaddrinfo() to resolve the hostname of the
			 * server and set ai_canonname.
			 */
			memset(&hints, 0, sizeof(hints));
			hints.ai_family = AF_UNSPEC;
			hints.ai_flags = AI_CANONNAME;
			rc = getaddrinfo(host, NULL, &hints, &ai);
			if (rc) {
				syslog(LOG_ERR, "Unable to resolve host address: %s [%s]",
				       host, gai_strerror(rc));
				break;
			}

			/* scan forward to first '.' in ai_canonnname */
			domainname = strchr(ai->ai_canonname, '.');
			if (!domainname) {
				rc = -EINVAL;
				freeaddrinfo(ai);
				break;
			}
			lowercase_string(domainname);
			rc = snprintf(fqdn, sizeof(fqdn), "%s%s",
					host, domainname);
			freeaddrinfo(ai);
			if (rc < 0 || (size_t)rc >= sizeof(fqdn)) {
				syslog(LOG_ERR, "Problem setting hostname in string: %ld", rc);
				rc = -EINVAL;
				break;
			}

			rc = handle_krb5_mech(oid, fqdn, &secblob, &sess_key, ccname);
			if (!rc)
				break;
		}

		if (!try_dns || !(have & DKD_HAVE_IP))
			break;

		rc = ip_to_fqdn(arg.ip, hostbuf, sizeof(hostbuf));
		if (rc)
			break;

		try_dns = 0;
		host = hostbuf;
		goto retry_new_hostname;
	default:
		syslog(LOG_ERR, "sectype: %d is not implemented", arg.sec);
		rc = 1;
		break;
	}

	if (rc) {
		syslog(LOG_DEBUG, "Unable to obtain service ticket");
		goto out;
	}

	/* pack SecurityBlob and SessionKey into downcall packet */
	datalen =
	    sizeof(struct cifs_spnego_msg) + secblob.length + sess_key.length;
	keydata = (struct cifs_spnego_msg *)calloc(sizeof(char), datalen);
	if (!keydata) {
		rc = 1;
		goto out;
	}
	keydata->version = arg.ver;
	keydata->flags = 0;
	keydata->sesskey_len = sess_key.length;
	keydata->secblob_len = secblob.length;
	memcpy(&(keydata->data), sess_key.data, sess_key.length);
	memcpy(&(keydata->data) + keydata->sesskey_len,
	       secblob.data, secblob.length);

	/* setup key */
	rc = keyctl_instantiate(key, keydata, datalen, 0);
	if (rc == -1) {
		syslog(LOG_ERR, "keyctl_instantiate: %s", strerror(errno));
		goto out;
	}

	/* BB: maybe we need use timeout for key: for example no more then
	 * ticket lifietime? */
	/* keyctl_set_timeout( key, 60); */
out:
	/*
	 * on error, negatively instantiate the key ourselves so that we can
	 * make sure the kernel doesn't hang it off of a searchable keyring
	 * and interfere with the next attempt to instantiate the key.
	 */
	if (rc != 0 && key == 0) {
		syslog(LOG_DEBUG, "Negating key");
		keyctl_negate(key, 1, KEY_REQKEY_DEFL_DEFAULT);
	}
	data_blob_free(&secblob);
	data_blob_free(&sess_key);
	SAFE_FREE(ccname);
	SAFE_FREE(arg.hostname);
	SAFE_FREE(arg.ip);
	SAFE_FREE(arg.username);
	SAFE_FREE(keydata);
	syslog(LOG_DEBUG, "Exit status %ld", rc);
	return rc;
}
Ejemplo n.º 6
0
/* This function is called by the parser to communicate events.  This
   callback communicates with the main program using a structure
   passed in OPAQUE. Should retrun 0 or set errno and return -1. */
static int
message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
{
  struct parse_info_s *info = opaque;

  if (debug)
    show_event (event);
  if (event == RFC822PARSE_T2BODY)
    {
      rfc822parse_field_t ctx;
      size_t off;
      char *p;

      info->mime_type = MT_NONE;
      info->transfer_encoding = TE_NONE;
      info->test_base64 = 0;
      info->got_probe = 0;
      info->no_mime = 0;
      ctx = rfc822parse_parse_field (msg, "Content-Type", -1);
      if (ctx)
        {
          const char *s1, *s2;
          s1 = rfc822parse_query_media_type (ctx, &s2);
          if (!s1)
            ;
          else if (!strcmp (s1, "application") 
                   && !strcmp (s2, "octet-stream"))
            info->mime_type = MT_OCTET_STREAM;
          else if (!strcmp (s1, "text") 
                   && !strcmp (s2, "html"))
            info->mime_type = MT_TEXT_HTML;
          else if (!strcmp (s1, "audio"))
            info->mime_type = MT_AUDIO;
          else if (!strcmp (s1, "image"))
            info->mime_type = MT_IMAGE;

          if (verbose)
            {
              printf ("# Content-Type: %s/%s", s1?s1:"", s2?s2:"");
              s1 = rfc822parse_query_parameter (ctx, "charset", 0);
              if (s1)
                printf ("; charset=%s", s1);
              putchar ('\n');
            }

          rfc822parse_release_field (ctx);
        }
      else
        {
          p = rfc822parse_get_field (msg, "MIME-Version", -1, NULL);
          if (p)
            free (p);
          else
            info->no_mime = 1;
        }

      if (verbose)
        {
          const char *s1;

          p = rfc822parse_get_field (msg, "Content-Disposition", -1, NULL);
          if (p)
            {
              printf ("# %s\n", p);
              free (p);
            }

          ctx = rfc822parse_parse_field (msg, "Content-Disposition", -1);
          if (ctx)
            {
              s1 = rfc822parse_query_parameter (ctx, "filename", 0);
              if (s1)
                printf ("# Content-Disposition has filename=`%s'\n", s1);
              rfc822parse_release_field (ctx);
            }
        }

      p = rfc822parse_get_field (msg, "Content-Transfer-Encoding", -1, &off);
      if (p)
        {
          lowercase_string (p+off);
          if (!strcmp (p+off, "base64"))
            info->transfer_encoding = TE_BASE64;
          free (p);
        }

      if (!info->top_seen)
        {
          info->top_seen = 1;
          p = rfc822parse_get_field (msg, "To", -1, NULL);
          if (p)
            {
              if ( strstr (p, "Werner Koch") )
                {
                  if (verbose)
                    fputs ("# Found known name in To\n", stdout);
                  info->wk_seen = 1;
                }
              free (p);
            }
          if (!info->wk_seen)
            {
              p = rfc822parse_get_field (msg, "Cc", -1, NULL);
              if (p)
                {
                  if ( strstr (p, "Werner Koch") )
                    {
                      if (verbose)
                        fputs ("# Found known name in Cc\n", stdout);
                      info->wk_seen = 1;
                    }
                  free (p);
                }
            }
        }

      if ((info->mime_type == MT_OCTET_STREAM
           || info->mime_type == MT_AUDIO
           || info->mime_type == MT_IMAGE)
          && info->transfer_encoding == TE_BASE64)
        info->test_base64 = 1;
      else if (info->mime_type == MT_TEXT_HTML)
        {
          if (!quiet)
            fputs ("HTML\n", stdout);
          if (opt_match_html && !info->wk_seen)
            exit (0);
        }

    }
  else if (event == RFC822PARSE_PREAMBLE)
    ;
  else if (event == RFC822PARSE_BOUNDARY || event == RFC822PARSE_LAST_BOUNDARY)
    {
      if (info->test_base64)
        info->got_probe = 1;
      info->test_base64 = 0;
    }
  else if (event == RFC822PARSE_BEGIN_HEADER)
    {
    }

  return 0;
}