Exemple #1
0
/*****************************************************************************
 * Open: open the file
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    sout_access_out_t   *p_access = (sout_access_out_t*)p_this;
    int                 fd;

    config_ChainParse( p_access, SOUT_CFG_PREFIX, ppsz_sout_options, p_access->p_cfg );

    if( !p_access->psz_path )
    {
        msg_Err( p_access, "no file name specified" );
        return VLC_EGENERIC;
    }

    bool overwrite = var_GetBool (p_access, SOUT_CFG_PREFIX"overwrite");
    bool append = var_GetBool( p_access, SOUT_CFG_PREFIX "append" );

    if (!strcmp (p_access->psz_access, "fd"))
    {
        char *end;

        fd = strtol (p_access->psz_path, &end, 0);
        if (!*p_access->psz_path || *end)
        {
            msg_Err (p_access, "invalid file descriptor: %s",
                     p_access->psz_path);
            return VLC_EGENERIC;
        }
        fd = vlc_dup (fd);
        if (fd == -1)
        {
            msg_Err (p_access, "cannot use file descriptor: %s",
                     vlc_strerror_c(errno));
            return VLC_EGENERIC;
        }
    }
    else
    if( !strcmp( p_access->psz_path, "-" ) )
    {
#if defined( _WIN32 ) || defined( __OS2__ )
        setmode (STDOUT_FILENO, O_BINARY);
#endif
        fd = vlc_dup (STDOUT_FILENO);
        if (fd == -1)
        {
            msg_Err (p_access, "cannot use standard output: %s",
                     vlc_strerror_c(errno));
            return VLC_EGENERIC;
        }
        msg_Dbg( p_access, "using stdout" );
    }
    else
    {
        const char *path = p_access->psz_path;
        char *buf = NULL;

        if (var_InheritBool (p_access, SOUT_CFG_PREFIX"format"))
        {
            buf = str_format_time (path);
            path_sanitize (buf);
            path = buf;
        }

        int flags = O_RDWR | O_CREAT | O_LARGEFILE;
        if (!overwrite)
            flags |= O_EXCL;
        if (!append)
            flags |= O_TRUNC;
#ifdef O_SYNC
        if (var_GetBool (p_access, SOUT_CFG_PREFIX"sync"))
            flags |= O_SYNC;
#endif
        do
        {
            fd = vlc_open (path, flags, 0666);
            if (fd != -1)
                break;
            if (fd == -1)
                msg_Err (p_access, "cannot create %s: %s", path,
                         vlc_strerror_c(errno));
            if (overwrite || errno != EEXIST)
                break;
            flags &= ~O_EXCL;
        }
        while (vlc_dialog_wait_question (p_access, VLC_DIALOG_QUESTION_NORMAL,
                                         _("Keep existing file"),
                                         _("Overwrite"), NULL, path,
                                         _("The output file already exists. "
                                         "If recording continues, the file will be "
                                         "overridden and its content will be lost.")) == 1);
        free (buf);
        if (fd == -1)
            return VLC_EGENERIC;
    }

    struct stat st;

    if (fstat (fd, &st))
    {
        msg_Err (p_access, "write error: %s", vlc_strerror_c(errno));
        close (fd);
        return VLC_EGENERIC;
    }

    p_access->pf_read  = Read;

    if (S_ISREG(st.st_mode) || S_ISBLK(st.st_mode))
    {
        p_access->pf_write = Write;
        p_access->pf_seek  = Seek;
    }
#ifdef S_ISSOCK
    else if (S_ISSOCK(st.st_mode))
    {
        p_access->pf_write = Send;
        p_access->pf_seek = NoSeek;
    }
#endif
    else
    {
        p_access->pf_write = WritePipe;
        p_access->pf_seek = NoSeek;
    }
    p_access->pf_control = Control;
    p_access->p_sys    = (void *)(intptr_t)fd;

    msg_Dbg( p_access, "file access output opened (%s)", p_access->psz_path );
    if (append)
        lseek (fd, 0, SEEK_END);

    return VLC_SUCCESS;
}
Exemple #2
0
/*
 * Write function called by secure transport for socket read.
 *
 * Function is based on Apples SSLSample sample code.
 */
static OSStatus st_SocketWriteFunc (SSLConnectionRef connection,
                                    const void *data,
                                    size_t *dataLength) {

    vlc_tls_t *session = (vlc_tls_t *)connection;
    vlc_tls_st_t *sys = (vlc_tls_st_t *)session;
    struct iovec iov = {
        .iov_base = (void *)data,
        .iov_len = *dataLength,
    };
    OSStatus retValue = noErr;

    while (iov.iov_len > 0) {
        ssize_t val = sys->sock->ops->writev(sys->sock, &iov, 1);
        if (val < 0) {
            switch (errno) {
                case EAGAIN:
                    retValue = errSSLWouldBlock;
                    sys->b_blocking_send = true;
                    break;

                case EPIPE:
                case ECONNRESET:
                    retValue = errSSLClosedAbort;
                    break;

                default:
                    msg_Err(sys->obj, "error while writing: %d", errno);
                    retValue = ioErr;
                    break;
            }
            break;
        }

        iov.iov_base = (char *)iov.iov_base + val;
        iov.iov_len -= val;
    }

    *dataLength -= iov.iov_len;
    return retValue;
}

static int st_validateServerCertificate (vlc_tls_t *session, const char *hostname) {

    vlc_tls_st_t *sys = (vlc_tls_st_t *)session;
    int result = -1;
    SecCertificateRef leaf_cert = NULL;

    SecTrustRef trust = NULL;
    OSStatus ret = SSLCopyPeerTrust(sys->p_context, &trust);
    if (ret != noErr || trust == NULL) {
        msg_Err(sys->obj, "error getting certifictate chain");
        return -1;
    }

    CFStringRef cfHostname = CFStringCreateWithCString(kCFAllocatorDefault,
                                                       hostname,
                                                       kCFStringEncodingUTF8);


    /* enable default root / anchor certificates */
    ret = SecTrustSetAnchorCertificates(trust, NULL);
    if (ret != noErr) {
        msg_Err(sys->obj, "error setting anchor certificates");
        result = -1;
        goto out;
    }

    SecTrustResultType trust_eval_result = 0;

    ret = SecTrustEvaluate(trust, &trust_eval_result);
    if (ret != noErr) {
        msg_Err(sys->obj, "error calling SecTrustEvaluate");
        result = -1;
        goto out;
    }

    switch (trust_eval_result) {
        case kSecTrustResultUnspecified:
        case kSecTrustResultProceed:
            msg_Dbg(sys->obj, "cerfificate verification successful, result is %d", trust_eval_result);
            result = 0;
            goto out;

        case kSecTrustResultRecoverableTrustFailure:
        case kSecTrustResultDeny:
        default:
            msg_Warn(sys->obj, "cerfificate verification failed, result is %d", trust_eval_result);
    }

    /* get leaf certificate */
    /* SSLCopyPeerCertificates is only available on OSX 10.5 or later */
#if !TARGET_OS_IPHONE
    CFArrayRef cert_chain = NULL;
    ret = SSLCopyPeerCertificates(sys->p_context, &cert_chain);
    if (ret != noErr || !cert_chain) {
        result = -1;
        goto out;
    }

    if (CFArrayGetCount(cert_chain) == 0) {
        CFRelease(cert_chain);
        result = -1;
        goto out;
    }

    leaf_cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_chain, 0);
    CFRetain(leaf_cert);
    CFRelease(cert_chain);
#else
    /* SecTrustGetCertificateAtIndex is only available on 10.7 or iOS */
    if (SecTrustGetCertificateCount(trust) == 0) {
        result = -1;
        goto out;
    }

    leaf_cert = SecTrustGetCertificateAtIndex(trust, 0);
    CFRetain(leaf_cert);
#endif


    /* check if leaf already accepted */
    CFIndex max = CFArrayGetCount(sys->p_cred->whitelist);
    for (CFIndex i = 0; i < max; ++i) {
        CFDictionaryRef dict = CFArrayGetValueAtIndex(sys->p_cred->whitelist, i);
        CFStringRef knownHost = (CFStringRef)CFDictionaryGetValue(dict, cfKeyHost);
        SecCertificateRef knownCert = (SecCertificateRef)CFDictionaryGetValue(dict, cfKeyCertificate);

        if (!knownHost || !knownCert)
            continue;

        if (CFEqual(knownHost, cfHostname) && CFEqual(knownCert, leaf_cert)) {
            msg_Warn(sys->obj, "certificate already accepted, continuing");
            result = 0;
            goto out;
        }
    }

    /* We do not show more certificate details yet because there is no proper API to get
       a summary of the certificate. SecCertificateCopySubjectSummary is the only method
       available on iOS and 10.6. More promising API functions such as
       SecCertificateCopyLongDescription also print out the subject only, more or less.
       But only showing the certificate subject is of no real help for the user.
       We could use SecCertificateCopyValues, but then we need to parse all OID values for
       ourself. This is too mad for just printing information the user will never check
       anyway.
     */

    const char *msg = N_("You attempted to reach %s. "
             "However the security certificate presented by the server "
             "is unknown and could not be authenticated by any trusted "
             "Certification Authority. "
             "This problem may be caused by a configuration error "
             "or an attempt to breach your security or your privacy.\n\n"
             "If in doubt, abort now.\n");
    int answer = vlc_dialog_wait_question(sys->obj,
                                          VLC_DIALOG_QUESTION_WARNING, _("Abort"),
                                          _("Accept certificate temporarily"),
                                          NULL, _("Insecure site"),
                                          vlc_gettext (msg), hostname);
    if (answer == 1) {
        msg_Warn(sys->obj, "Proceeding despite of failed certificate validation");

        /* save leaf certificate in whitelist */
        const void *keys[] = {cfKeyHost, cfKeyCertificate};
        const void *values[] = {cfHostname, leaf_cert};
        CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault,
                                                   keys, values, 2,
                                                   &kCFTypeDictionaryKeyCallBacks,
                                                   &kCFTypeDictionaryValueCallBacks);
        if (!dict) {
            msg_Err(sys->obj, "error creating dict");
            result = -1;
            goto out;
        }

        CFArrayAppendValue(sys->p_cred->whitelist, dict);
        CFRelease(dict);

        result = 0;
        goto out;

    } else {
        result = -1;
        goto out;
    }

out:
    CFRelease(trust);

    if (cfHostname)
        CFRelease(cfHostname);
    if (leaf_cert)
        CFRelease(leaf_cert);

    return result;
}