openssl BIO_do_connect returns 0 for ssl - ssl

Here's my simple openssl client test case trying to connect to google.com:443.
According to the manual, BIO_do_connect should return 1, 0 or -1.
Google didn't find me anyone for whom it returns 0, which it does for me.
#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
int main()
{
SSL_load_error_strings();
SSL_library_init();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
SSL_CTX *p_ssl_ctx = NULL;
SSL *p_ssl = NULL;
BIO * bio = NULL;
int r = 0;
// init ssl context
p_ssl_ctx = SSL_CTX_new(SSLv2_client_method()); /* Create new context */
if (p_ssl_ctx == NULL)
{
ERR_print_errors_fp(stderr);
return 3;
}
const char *store_path = "/etc/ssl/certs/ca-certificates.crt";
r = SSL_CTX_load_verify_locations(p_ssl_ctx, store_path, NULL);
if (r == 0) {
fprintf(stderr, "Unable to load the trust store from %s.\n", store_path);
return 4;
}
bio = BIO_new_ssl_connect(p_ssl_ctx);
if (!bio) {
fprintf(stderr, "no bio \n");
return 5;
}
BIO_get_ssl(bio, &p_ssl);
if (!(p_ssl)) {
fprintf(stderr, "no ssl\n");
return 6;
}
SSL_set_mode(p_ssl, SSL_MODE_AUTO_RETRY);
BIO_set_conn_hostname(bio, "www.google.com:443");
r = BIO_do_connect(bio);
if (r < 1) {
fprintf(stderr, "BIO_new_ssl_connect failed: %lu (0x%lx)\n", r, r);
fprintf(stderr, "Error: %s\n", ERR_reason_error_string(ERR_get_error()));
fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
ERR_print_errors_fp(stderr);
perror("bio");
return 7;
}
if (SSL_get_verify_result(p_ssl) != X509_V_OK) {
fprintf(stderr, "Unable to verify connection result.\n");
return 8;
}
return 0;
}
returns:
BIO_new_ssl_connect failed: 0 (0x0)
Error: (null)
error:00000000:lib(0):func(0):reason(0)
bio: Success
so how do i get the actual error out of this?

For getting the last state of your SSL connection in your code you can add something like fprintf(stderr,"p_ssl state: %s\n",SSL_state_string_long(p_ssl));.
More generally I suggest you to add an info callback like this : http://www.openssl.org/docs/ssl/SSL_CTX_set_info_callback.html
For your case, you must replace SSLv2_client_method() by something like TLSv1_client_method().

Related

TLS Session Resumption with OpenSSL server and SChannel client

I must use the RFC5077 TLS session resumption. My Client use Windows SChannel and server usually uses OpenSSL. In my test, following result.
OpenSSL 1.1.0 (or later) and SChannel: Always session reused, SChannel send previous Session Ticket.
OpenSSL 1.0.2 (any revision) and Schannel: Always new session, SChannel does not send Session Ticket.
OpenSSL and OpenSSL: Always session reused.
So I want to know that
Why Schannel don't use TLS session resumption only for OpenSSL 1.0.2?
The difference between 1.0.2 and 1.1.0.
How to use TLS session resumption at OpenSSL 1.0.2 and SChannel?
Server code: Simple TLS Server
Client code: Windows C++
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define SECURITY_WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WinSock2.h>
#include <sspi.h>
#include <schannel.h>
#include <stdio.h>
#include <vector>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Secur32.lib")
struct WSA {
WSA() {
WSADATA wsaData;
if (auto result = WSAStartup(WINSOCK_VERSION, &wsaData))
throw result;
}
~WSA() {
WSACleanup();
}
};
struct Credential : CredHandle {
Credential() {
SCHANNEL_CRED cred = { .dwVersion = SCHANNEL_CRED_VERSION, .dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_MANUAL_CRED_VALIDATION };
if (auto ss = AcquireCredentialsHandleW(nullptr, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, nullptr, &cred, nullptr, nullptr, this, nullptr); ss != SEC_E_OK)
throw ss;
}
~Credential() {
FreeCredentialsHandle(this);
}
};
struct Socket {
SOCKET s;
Socket(const char* target, int port) {
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(target);
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET)
throw WSAGetLastError();
if (connect(s, reinterpret_cast<const SOCKADDR*>(&addr), sizeof addr))
throw WSAGetLastError();
u_long val = 1;
ioctlsocket(s, FIONBIO, &val);
}
~Socket() {
closesocket(s);
}
auto Read() {
for (std::vector<unsigned char> result;;) {
char buffer[2048];
if (auto read = recv(s, buffer, sizeof buffer, 0); read == 0)
return result;
else if (read == SOCKET_ERROR) {
if (auto lastError = WSAGetLastError(); lastError != WSAEWOULDBLOCK)
throw lastError;
if (!empty(result))
return result;
Sleep(0);
} else
result.insert(end(result), buffer, buffer + read);
}
}
void Write(void* data, int length) {
for (auto p = reinterpret_cast<const char*>(data); 0 < length;) {
auto sent = send(s, p, length, 0);
if (sent == 0)
throw 0;
else if (sent == SOCKET_ERROR)
throw WSAGetLastError();
p += sent;
length -= sent;
}
}
};
int main() {
WSA wsa;
Credential credential;
for (int i = 0; i < 5; i++) {
Socket socket{ "127.0.0.1", 4433 };
std::vector<unsigned char> read;
auto first = true;
CtxtHandle context;
for (SECURITY_STATUS ss = SEC_I_CONTINUE_NEEDED; ss == SEC_I_CONTINUE_NEEDED;) {
SecBuffer inbuf[] = {
{ .BufferType = SECBUFFER_EMPTY },
{ .BufferType = SECBUFFER_EMPTY },
};
if (!first) {
auto data = socket.Read();
read.insert(end(read), begin(data), end(data));
inbuf[0] = { static_cast<unsigned long>(read.size()), SECBUFFER_TOKEN, read.data() };
}
SecBufferDesc indesc = { SECBUFFER_VERSION, 2, inbuf };
SecBuffer outbuf = { .BufferType = SECBUFFER_TOKEN };
SecBufferDesc outdesc = { SECBUFFER_VERSION, 1, &outbuf };
unsigned long attr = 0;
ss = InitializeSecurityContextW(&credential, first ? nullptr : &context, L"localhost", ISC_REQ_ALLOCATE_MEMORY, 0, SECURITY_NETWORK_DREP, &indesc, 0, &context, &outdesc, &attr, nullptr);
if (FAILED(ss))
throw ss;
first = false;
read.erase(begin(read), end(read) - (inbuf[1].BufferType == SECBUFFER_EXTRA ? inbuf[1].cbBuffer : 0));
if (outbuf.cbBuffer != 0) {
socket.Write(outbuf.pvBuffer, outbuf.cbBuffer);
FreeContextBuffer(outbuf.pvBuffer);
}
}
for (;;) {
SecBuffer buffer[] = {
{ static_cast<unsigned long>(read.size()), SECBUFFER_DATA, read.data() },
{ .BufferType = SECBUFFER_EMPTY },
{ .BufferType = SECBUFFER_EMPTY },
{ .BufferType = SECBUFFER_EMPTY },
};
SecBufferDesc desc{ SECBUFFER_VERSION, 4, buffer };
if (auto ss = DecryptMessage(&context, &desc, 0, nullptr); ss == SEC_I_CONTEXT_EXPIRED)
break;
else if (ss == SEC_E_OK) {
if (buffer[1].BufferType == SECBUFFER_DATA && 0 < buffer[1].cbBuffer && buffer[1].pvBuffer)
printf("%.*s", buffer[1].cbBuffer, reinterpret_cast<const char*>(buffer[1].pvBuffer));
read.erase(begin(read), end(read) - (buffer[3].BufferType == SECBUFFER_EXTRA ? buffer[3].cbBuffer : 0));
} else if (ss != SEC_E_INCOMPLETE_MESSAGE)
throw ss;
if (auto data = socket.Read(); empty(data))
break;
else
read.insert(end(read), begin(data), end(data));
}
if (auto ss = DeleteSecurityContext(&context); ss != SEC_E_OK)
throw ss;
}
}
I'm a maintainer of ftp client. Some ftps server requires that DATA connection must reuse the TLS session of CONTROL connection for security.
At Windows Update 2019/10, RFC7627 Extended Master Secret was enabled. SChannel requires RFC7627 EMS support when RFC5077 TLS Session Resumption.
OpenSSL suport RFC7627 extended master secret from 1.1.0. So SChannel cannot reuse TLS session with OpenSSL 1.0.2.

OpenLDAP - Enabling CRL check for LDAP TLS connections

I have a client that connects to LDAP server using TLS. For this connection, I want to enable CRL check and reject the connection only if any server/client certificates are revoked.
In special cases (like CRL missing, CRL expired) I want to ignore the error and establish the connection.
So I though to overwrite the default SSL verify call back to ignore the specific errors.
But the call back is not called at all. Always only default call-back is called.
Here is my call back:
static int verify_callback(int ok, X509_STORE_CTX *ctx)
{
X509* cert = X509_STORE_CTX_get_current_cert(ctx);
if (ok)
return ok;
int sslRet = X509_STORE_CTX_get_error(ctx);
const char* err = NULL;
switch (sslRet)
{
case X509_V_ERR_UNABLE_TO_GET_CRL:
case X509_V_ERR_CRL_HAS_EXPIRED:
case X509_V_ERR_CRL_NOT_YET_VALID:
printf( "CRL: Verification failed... but ignored : %d\n", sslRet);
return 1;
default:
err = X509_verify_cert_error_string(sslRet);
if (err)
printf( "CRL: Failed to verify : %s\n",err);
return 0;
}
return sslRet;
}
Default verify call-back is overwritten using the ldap call-back set option:
void ldap_tls_cb(LDAP * ld, SSL * ssl, SSL_CTX * ctx, void * arg)
{
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER , verify_callback);
printf("verify call back is set...\n");
return;
}
Main Program:
int main( int argc, char **argv )
{
LDAP *ldap;
int auth_method = LDAP_AUTH_SIMPLE; //LDAP_AUTH_SASL
int ldap_version = LDAP_VERSION3;
char *ldap_host = "10.104.40.35";
int ldap_port = 389;
if ( (ldap = ldap_init(ldap_host, ldap_port)) == NULL ) {
perror( "ldap_init failed" );
return( EXIT_FAILURE );
}
int result = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option failed!");
return(EXIT_FAILURE);
}
int requireCert = LDAP_OPT_X_TLS_DEMAND;
result = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &requireCert);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option - req cert -failed!");
return(EXIT_FAILURE);
}
result = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, "/etc/certs/Cert.pem");
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option - cert file - failed!");
return(EXIT_FAILURE);
}
int crlvalue = LDAP_OPT_X_TLS_CRL_ALL;
result =ldap_set_option(NULL, LDAP_OPT_X_TLS_CRLCHECK, &crlvalue);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option failed!");
return(EXIT_FAILURE);
}
int debug = 7;
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
result = ldap_set_option(ldap, LDAP_OPT_X_TLS_CONNECT_CB, (void *)ldap_tls_cb);
if (result != LDAP_SUCCESS) {
fprintf(stderr, "ldap_set_option(LDAP_OPT_X_TLS_CONNECT_CB): %s\n", ldap_err2string(result));
return(1);
}
int msgidp = 0;
result = ldap_start_tls(ldap,NULL,NULL,&msgidp);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "start tls failed!");
return result;
} else {
printf("Start tls success.\n");
}
LDAPMessage *resultm;
struct timeval timeout;
result = ldap_result(ldap, msgidp, 0, &timeout, &resultm );
if ( result == -1 || result == 0 ) {
printf("ldap_result failed;retC=%d \n", result);
return result;
}
result = ldap_parse_extended_result(ldap, resultm, NULL, NULL, 0 );
if ( result == LDAP_SUCCESS ) {
result = ldap_install_tls (ldap);
printf("installing tls... %s\n", ldap_err2string(result));
}
int request_id = 0;
result = ldap_sasl_bind(ldap, "", LDAP_SASL_SIMPLE, NULL, 0, 0, &request_id);
if ( result != LDAP_SUCCESS ) {
fprintf(stderr, "ldap_x_bind_s: %s\n", ldap_err2string(result));
printf("LDAP bind error .. %d\n", result);
return(EXIT_FAILURE);
} else {
printf("LDAP connection successful.\n");
}
ldap_unbind(ldap);
return(EXIT_SUCCESS);
}
can someone help to check why my verify call-back is not called?
I think you need to set the callback on the SSL object directly instead of the context, so
void ldap_tls_cb(LDAP * ld, SSL * ssl, SSL_CTX * ctx, void * arg)
{
SSL_set_verify(ssl, SSL_VERIFY_PEER, verify_callback);
printf("verify call back is set...\n");
return;
}
The reason for this is that the SSL handle has already been initialised by the time your connect callback is called (see the OpenLDAP code), and
it's too late to set this callback through the context at that point:
If no special callback was set before, the default callback for the underlying ctx is used, that was valid at the time ssl was created with SSL_new(3).
OpenLDAP can be built with GnuTLS, so you may need to check that it's using OpenSSL before setting the callback. The LDAP_OPT_X_TLS_PACKAGE option could be used for this (note that I haven't tested this code):
char* package = NULL;
int result = ldap_get_option(NULL, LDAP_OPT_X_TLS_PACKAGE, (void *)&package);
if (result != LDAP_OPT_SUCCESS) {
ldap_perror(ldap, "ldap_get_option failed!");
return(EXIT_FAILURE);
} else {
if (strcmp(package, "OpenSSL") == 0) {
// Set your callback
}
ldap_memfree(package);
}

libssh2: How to send data through libssh2_channel_write

EDIT:
Here's the complete code. modified the code to work with a router but the use case is same. Once i issue the password using libssh2_channel_write() subsequent libssh2_channel_read() fails with LIBSSH2_ERROR_SOCKET_RECV. Not sure why. I am unable to send subsequent commands to the remote device and get their output.
Logic was to execute a command on the remote device ( libssh2_channel_exec ). This command execution would throw a password to be entered by the client. Now read the stream via libssh2_channel_read() and ensure that the password is being asked and write the password to the channel via libssh2_channel_write(). Ensure the password is accepted on the remote device by doing subsequent reads [ THIS IS WHERE THE LIB IS FAILING WITH ERROR_SOCKET_RECV ] and then send the command to be executed via libssh2_channel_write() and read the command output. Am i missing something ?
for( ;; )
{
/* loop until we block */
int rc;
do
{
char buffer[0x4000];
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
char *enable = "check-password\n";
int ret;
bytecount += rc;
fprintf(stderr, "We read [%d] bytes:\n", bytecount);
fputc('[', stderr);
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
fputc(']', stderr);
if ( strstr(buffer, "Password:") != NULL ){
fprintf(stderr, "Sending the password now\n");
while((ret = libssh2_channel_write(channel, enable, strlen(enable))) == LIBSSH2_ERROR_EAGAIN) {
printf("ERROR_EAGAIN - sending password again\n");
}
fprintf(stderr, "Wrote [%d] bytes: \n", ret);
flag = 1;
continue;
}
if (!flag){ // start
char *cmd = "show clock\n";
int ret;
fprintf(stderr, "THIS Fetching show clock command now\n");
while((ret = libssh2_channel_write(channel, cmd, strlen(cmd))) == LIBSSH2_ERROR_EAGAIN) {
printf("ERROR_EAGAIN - sending show clock again\n");
}
flag = 1;
} // end
}
else {
if(rc != LIBSSH2_ERROR_EAGAIN)
fprintf(stderr, "libssh2_channel_read returned [%d]:\n ", rc);
}
}
while( rc > 0 );
/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc == LIBSSH2_ERROR_EAGAIN )
{
int check;
check = waitsocket(sock, session);
}
else
break;
}

LDAP Authentication, ldap_sasl_bind_s not working but ldap_simple_bind_s works

I have a problem where in ldap_sasl_bind_s does not work, but ldap_simple_bind_s works.
The strange thing is, ldap_sasl_bind_s works even with wrong passwords and gives user the feeling that he has entered a correct password.
PFA code snippet of the problem and suggest me if anything is wrong with my approach.
{
int rc, aReturnVal = 0;
NSString *aUserDN = [NSString stringWithFormat:#"uid=%s,cn=users,dc=example,dc=com", username];
char* userDN = (char*)[aUserDN UTF8String];
rc = ldap_simple_bind_s (
ld,
userDN,
password
);
// TODO: ldap_simple_bind_s is a deprecated method and should not be used for long. ldap_sasl_bind_s is the right method, but is not working for now.
// Find the reason and get this code up and running.
// struct berval *servcred;
// struct berval cred;
// cred.bv_val = password; // my password
// cred.bv_len = strlen(password);
// rc = ldap_sasl_bind_s (
// ld,
// userDN,
// "DIGEST-MD5",
// &cred,
// NULL,
// NULL,
// &servcred
// );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_sasl_bind: %s\n", ldap_err2string( rc ) );
} else {
aReturnVal = 1;
}
return aReturnVal;
}
I have initialized the LDAP using following code SNIP:
rc = ldap_initialize(&ld, HOSTNAME);
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
ldap_set_option( ld, LDAP_OPT_REFERRALS, 0 );
I need to be able to login with correct user name and when user tries to enter wrong user name, ldap should say so.
I have referred to following links and their related links to get to this conclusion:
LDAP - How to check a username/password combination?
How to do password authentication for a user using LDAP?
Digest-MD5 auth is more complicated than just sending a bind DN and password. You'll need to use ldap_sasl_interactive_bind_s and provide a callback so the SASL library can combine your credentials with the server-provided nonce.
This code (adapted from this blog post) works for me against an Active Directory server:
#include <stdio.h>
#include <stdlib.h>
#include <ldap.h>
#include <sasl/sasl.h>
typedef struct
{
char *username;
char *password;
} my_authdata;
int my_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in)
{
my_authdata *auth = (my_authdata *)defaults;
sasl_interact_t *interact = (sasl_interact_t *)in;
if(ld == NULL) return LDAP_PARAM_ERROR;
while(interact->id != SASL_CB_LIST_END)
{
char *dflt = (char *)interact->defresult;
switch(interact->id)
{
case SASL_CB_GETREALM:
dflt = NULL;
break;
case SASL_CB_USER:
case SASL_CB_AUTHNAME:
dflt = auth->username;
break;
case SASL_CB_PASS:
dflt = auth->password;
break;
default:
printf("my_sasl_interact asked for unknown %ld\n",interact->id);
}
interact->result = (dflt && *dflt) ? dflt : (char *)"";
interact->len = strlen((char *)interact->result);
interact++;
}
return LDAP_SUCCESS;
}
int main(int argc, char *argv[])
{
if(argc < 3)
{
fprintf(stderr, "Usage: dmd5-bind [username] [password]\n");
return -1;
}
int rc;
LDAP *ld = NULL;
static my_authdata auth;
auth.username = argv[1];
auth.password = argv[2];
char *sasl_mech = ber_strdup("DIGEST-MD5");
char *ldapuri = ber_strdup("ldap://your.server.name.here");
int protocol = LDAP_VERSION3;
unsigned sasl_flags = LDAP_SASL_QUIET;
char *binddn = NULL;
rc = ldap_initialize(&ld, ldapuri);
if(rc != LDAP_SUCCESS)
{
fprintf(stderr, "ldap_initialize: %s\n", ldap_err2string(rc));
return rc;
}
if(ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &protocol) != LDAP_OPT_SUCCESS)
{
fprintf(stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", protocol);
return -1;
}
rc = ldap_sasl_interactive_bind_s(ld,
binddn,
sasl_mech,
NULL,
NULL,
sasl_flags,
my_sasl_interact,
&auth);
if(rc != LDAP_SUCCESS)
{
ldap_perror(ld, "ldap_sasl_interactive_bind_s");
ldap_unbind_ext_s(ld, NULL, NULL);
return rc;
}
fprintf(stdout, "Authentication succeeded\n");
rc = ldap_unbind_ext_s(ld, NULL, NULL);
sasl_done();
sasl_client_init(NULL);
return rc;
}

WMV Converter Fails FFMpeg

I just cann't seem to get the FFMpeg working with using the library. Everytime I try to convert asf file to wmv. I get the following issue on run time:
[wmv1 # 0x81ee000]error, slice code was 2
[wmv1 # 0x81ee000]header damaged
This my code:
static void audio_decode_example(const char *outfilename, const char *filename)
{
AVCodec *codec;
AVCodecContext *c= NULL;
int out_size, len, in_size;
FILE *f, *outfile;
uint8_t *outbuf;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
av_init_packet(&avpkt);
printf("Audio decoding\n");
/* find the mpeg audio decoder */
codec = avcodec_find_decoder(CODEC_ID_WMV1);
if (!codec) {
fprintf(stderr, "codec not found\n");
return;
}
c= avcodec_alloc_context2(CODEC_TYPE_AUDIO);
/* open it */
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open codec\n");
return;
}
outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
return;
}
outfile = fopen(outfilename, "wb");
if (!outfile) {
av_free(c);
return;
}
/* decode until eof */
avpkt.data = inbuf;
len = avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);
NSLog(#"%d", avpkt.size);
while (avpkt.size > 0) {
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
len = avcodec_decode_audio2(c, (short *)outbuf, &out_size, inbuf,len);// avpkt.size);
NSLog(#"%d", len);
if (len < 0) {
fprintf(stderr, "Error while decoding\n");
fclose(outfile);
return;
}
if (out_size > 0) {
/* if a frame has been decoded, output it */
fwrite(outbuf, 1, out_size, outfile);
}
avpkt.size -= len;
avpkt.data += len;
if (avpkt.size < AUDIO_REFILL_THRESH) {
/* Refill the input buffer, to avoid trying to decode
* incomplete frames. Instead of this, one could also use
* a parser, or use a proper container format through
* libavformat. */
memmove(inbuf, avpkt.data, avpkt.size);
avpkt.data = inbuf;
len = fread(avpkt.data + avpkt.size, 1,
INBUF_SIZE - avpkt.size, f);
if (len > 0)
avpkt.size += len;
}
}
fclose(outfile);
fclose(f);
free(outbuf);
avcodec_close(c);
av_free(c);
}
I have try the command line utilities and it successfully convert the file. Any help would be helpfully. thanks
Make the mistake of opening the wrong file