Example #1
0
//--------------------------------------------------
// Checks if this file exists
// szFileName - file name
// returns 1 if exists
// AA 2004/05/20 debuggeri all viga, kui null pikkus
//--------------------------------------------------
EXP_OPTION int checkFileExists(const char* szFileName)
{
    FILE* hFile = 0;
    int exists = 0;
#ifdef WIN32
    int i = 0, err = ERR_OK;
    wchar_t *convFileName = 0;
#endif
    if(szFileName && strlen(szFileName) > 0) {
#ifdef WIN32
        err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i);
        if((hFile = _wfopen(convFileName, L"r")) != NULL) {
#else
        if((hFile = fopen(szFileName, "r")) != NULL) {
#endif
            exists = 1;
            fclose(hFile);
        }
    }
#ifdef WIN32
    if(convFileName) free(convFileName);
#endif
    return exists;
}


//================< certficate info functions> =================================

//--------------------------------------------------
// Returns the user signatures certificate data
// pSignInfo - signature object
// returns cert data. This is actually X509*. Obsolete function
//--------------------------------------------------
EXP_OPTION X509* getSignCertData(const SignatureInfo* pSignInfo)
{
    RETURN_OBJ_IF_NULL(pSignInfo, 0);
    return ddocSigInfo_GetSignersCert(pSignInfo);
}
//--------------------------------------------------
// Reads in signed XML document and extracts the desired data file
// pSigDoc - signed document object if exists. Can be NULL
// szFileName - digidoc filename
// szDataFileName - name of the file where to store embedded data.
// szDocId - DataFile Id atribute value
// szCharset - convert DataFile content to charset
//--------------------------------------------------
EXP_OPTION int ddocExtractDataFile(SignedDoc* pSigDoc, const char* szFileName,
                                   const char* szDataFileName, const char* szDocId,
                                   const char* szCharset)
{
    FILE *fIn = 0, *fOut = 0;
    int err = ERR_OK, i, nRead, lt, la, lc, j, ld, lb, l, eState = 0, fs = 0;
    long len, lExtr = 0, lSize = 0;
    char chars[1050], tag[100], attr[100], con[1030], dec[70], b64line[70];
    unsigned char b64 = 0, nNc = 0, bFound = 0;
    void *pBuf;
    EVP_ENCODE_CTX ectx;
#ifdef WIN32
    wchar_t *convFileName = 0, *convDataFileName = 0;
    i= 0;
    err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i);
    ddocDebug(3, "ddocExtractDataFile", "file: %s, conv-file: %s len: %d", szFileName, convFileName, i);
    i= 0;
    err = utf82unicode((const char*)szDataFileName, (char**)&convDataFileName, &i);
    ddocDebug(3, "ddocExtractDataFile", "dfile: %s, conv-dfile: %s len: %d", szDataFileName, convDataFileName, i);
#endif

    RETURN_IF_NULL_PARAM(szFileName);
    RETURN_IF_NULL_PARAM(szDataFileName);
    RETURN_IF_NULL_PARAM(szDocId);
    RETURN_IF_NULL_PARAM(szCharset);
    clearErrors();
    ddocDebug(3, "ddocExtractDataFile", "SigDoc: %s, docid: %s, digidoc: %s, file: %s, charset: %s", (pSigDoc ? "OK" : "NULL"), szDocId, szFileName, szDataFileName, szCharset);
    if(szCharset && !strcmp(szCharset, "NO-CHANGE"))
        nNc = 1;
    // try reading from memory if already cached?
    nRead = ddocGetDataFileCachedData(pSigDoc, szDocId, &pBuf, &len);
    if(pBuf) { // gotcha
        ddocDebug(3, "ddocSaxExtractDataFile", "Using cached data: %d bytes", len);
#ifdef WIN32
        if((fOut = _wfopen(convDataFileName, L"wb")) != NULL) {
#else
        if((fOut = fopen(szDataFileName, "wb")) != NULL) {
#endif
            fwrite(pBuf, 1, len, fOut);
            fclose(fOut);
        } else {
            free(pBuf);
            ddocDebug(1, "ddocSaxExtractDataFile", "Error writing file: %s", szDataFileName);
            SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE);
        }
        free(pBuf);
        return nRead;
    }
    // open ddoc file
#ifdef WIN32
    if((fIn = _wfopen(convFileName, L"rb")) != NULL) {
#else
    if((fIn = fopen(szFileName, "rb")) != NULL) {
#endif
        ddocDebug(3, "ddocExtractDataFile", "Opened ddoc-file: %s", szFileName);
        do {
            nRead = fread(chars, 1, 1024, fIn);
            chars[nRead] = 0;
            ddocDebug(6, "ddocExtractDataFile", "Parsing %d bytes: \n%s\n", nRead, chars);
            // handle read data
            for(i = 0; i < nRead; i++) {
                switch(eState) {
                case ST_START: // search '<?xml'
                    if(chars[i] == '<' &&
                            !strncmp(chars+i, "<?xml", 5)) {
                        eState = ST_XML;
                        i += 4;
                    }
                    break;
                case ST_XML: // search '<'
                    if(chars[i] == '<') {
                        eState = ST_TAG_NM;
                        lt = 0;
                        tag[lt] = 0;
                    }
                    break;
                case ST_TAG_NM: // read tag name
                    if(isalnum(chars[i]) || chars[i] == ':' || chars[i] == '/') {
                        if(lt < sizeof(tag)-1) {
                            tag[lt] = chars[i];
                            tag[++lt] = 0;
                        } else {
                            ddocDebug(1, "ddocSaxExtractDataFile", "Invalid xml tag-len > %d", sizeof(tag));
                            SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ);
                        }
                    } else if(chars[i] == '>') { // tag ended - content
                        eState = ST_CON;
                    } else { // expecting atributes
                        eState = ST_TAG_WS;
                    }
                    break;
                case ST_TAG_WS:
                    if(chars[i] == '>') {
                        if(bFound) {
                            eState = ST_DF_CON;
                            if(b64)
                                EVP_DecodeInit(&ectx);
                        } else
                            eState = ST_CON; // tag endded - content
                        lc = 0;
                        con[lc] = 0;
                    } else if(isalnum(chars[i])) {
                        eState = ST_ATTR_NM; // attr name started
                        la = 0;
                        attr[la] = chars[i];
                        attr[++la] = 0;
                    }
                    break;
                case ST_ATTR_NM:
                    if(isalnum(chars[i])) {
                        if(la < (int)sizeof(attr)-1) {
                            attr[la] = chars[i];
                            attr[++la] = 0;
                        }
                        else
                            ddocDebug(1, "ddocExtractDataFile", "Truncating attr name: %s", attr);
                        break;
                        //19.11.08 added support for '
                    } else if(chars[i] == '\"'/*|| chars[i] == '\''*/) {
                        eState = ST_ATTR_CON;
                        lc = 0;
                        con[lc] = 0;
                        fs = 2;
                    } else if(chars[i] == '\'' && fs==0) {
                        eState = ST_ATTR_CON;
                        lc = 0;
                        con[lc] = 0;
                        fs = 1;
                    } else {
                        eState = ST_ATTR_WS;
                    }
                    break;
                case ST_ATTR_WS:
                    //19.11.08 added support for '
                    if(chars[i] == '\"'/*|| chars[i] == '\''*/) {
                        eState = ST_ATTR_CON;
                        lc = 0;
                        con[lc] = 0;
                    } else if(chars[i] == '\'' && fs==1)  {
                        eState = ST_ATTR_CON;
                        lc = 0;
                        con[lc] = 0;
                    } else {
                        eState = ST_TAG_WS;
                    }
                    break;
                case ST_ATTR_CON:
                    //19.11.08 added support for '
                    if(chars[i] != '\"' /*&& chars[i] != '\''*/) {
                        if(lc < (int)sizeof(con)-1) {
                            con[lc] = chars[i];
                            con[++lc] = 0;
                        } else
                            ddocDebug(1, "ddocExtractDataFile", "Truncating attr content: %s", attr);
                    } else if(chars[i] == '\'' && fs==1)  {
                        if(lc < (int)sizeof(con)-1) {
                            con[lc] = chars[i];
                            con[++lc] = 0;
                        } else
                            ddocDebug(1, "ddocExtractDataFile", "Truncating attr content: %s", attr);
                    } else {
                        eState = ST_TAG_WS;
                        // attribute value complete
                        if(!strcmp(tag, "DataFile")) {
                            //	ddocDebug(3, "ddocSaxExtractDataFile", "DataFile start, attr: %s", attr);
                            if(!strcmp(attr, "ContentType")) {
                                b64 = (!strcmp(con, "EMBEDDED_BASE64")) ? 1 : 0;
                                lb = 0;
                                b64line[0] = 0;
                            }
                            if(!strcmp(attr, "Size") && bFound) {
                                lSize = atol(con);
                            }
                            if(!strcmp(attr, "Id")) {
                                ddocDebug(3, "ddocSaxExtractDataFile", "Found Id: %s searching id: %s", con, szDocId);
                                if(!strcmp(con, szDocId)) {
                                    bFound = 1;
#ifdef WIN32
                                    fOut = _wfopen(convDataFileName, L"wb");
                                    ddocDebug(3, "ddocSaxExtractDataFile", "Opening file: %s handle: %s", convDataFileName, (fOut ? "OK" : "NULL"));
#else
                                    fOut = fopen(szDataFileName, "wb");
                                    ddocDebug(3, "ddocSaxExtractDataFile", "Opening file: %s handle: %s", szDataFileName, (fOut ? "OK" : "NULL"));
#endif
                                    if(!fOut) {
                                        SET_LAST_ERROR(ERR_FILE_WRITE);
                                        err = ERR_FILE_WRITE;
                                        return err;
                                    }
                                }
                            }
                        }
                    }
                    break;
                case ST_CON:
                    if(chars[i] == '<') {
                        eState = ST_TAG_NM;
                        lt = 0;
                        tag[lt] = 0;
                    } else {
                        //con[lc] = chars[i];
                        //con[++lc] = 0;
                    }
                    break;
                case ST_DF_START: // find tag end
                    if(chars[i] == '>') {
                        eState = ST_DF_CON;
                        lc = 0;
                        con[lc] = 0;
                        if(b64)
                            EVP_DecodeInit(&ectx);
                    }
                    break;
                case ST_DF_CON:
                    if(chars[i] == '<') {
                        eState = ST_DF_TAG;
                        lt = 0;
                        tag[lt] = 0;
                    } else {
                        if(lc < (int)sizeof(con) - 1) {
                            if(b64 && !nNc) {
                                for(l = 0; l < lc; ) {
                                    while(lb < 64 && l < lc && l < sizeof(con)) {
                                        if(con[l] != '\n' && con[l] != '\r')
                                            b64line[lb++] = con[l];
                                        l++;
                                    }
                                    if(lb == 64) {
                                        b64line[lb++] = '\n';
                                        b64line[lb] = 0;
                                        ld = sizeof(dec);
                                        dec[0] = 0;
                                        EVP_DecodeUpdate(&ectx, (unsigned char*)dec, &ld, (unsigned char*)b64line, lb);
                                        lExtr += ld;
                                        if(ld > 0)
                                            fwrite(dec, 1, ld, fOut);
                                        lb = 0;
                                    }
                                }
                            } else if(nNc || !b64) {
                                lExtr += lc;
                                fwrite(con, 1, lc, fOut);
                            }
                            lc = 0;
                        }
                        if(lc < sizeof(con)-1) {
                            con[lc] = chars[i];
                            con[++lc] = 0;
                        }
                    }
                    break;
                case ST_DF_TAG:
                    if(/*isalnum(chars[i]) || chars[i] == ':' || chars[i] == '/' ||*/ chars[i] != '>') {
                        if(lt < sizeof(tag)-1) {
                            tag[lt] = chars[i];
                            tag[++lt] = 0;
                        } else {
                            ddocDebug(1, "ddocSaxExtractDataFile", "Invalid xml tag-len > %d", sizeof(tag));
                            SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ);
                        }
                    } else { // DF intenal tag name ready
                        if(!strcmp(tag, "/DataFile")) { // end of DF
                            eState = ST_DF_END;
                        } else { // wrong tag - this is content
                            if(lc < sizeof(con)-1) {
                                con[lc] = '<';
                                for(j = 0; j < lt; j++)
                                    con[++lc] = tag[j];
                                con[++lc] = '>';
                                con[++lc] = 0;
                            }
                            eState = ST_DF_CON;
                        }
                    }
                    if(eState != ST_DF_END)
                        break;
                case ST_DF_END:
                    if(b64 && !nNc) {
                        if(lc > 0) {
                            for(l = 0; l < lc; ) {
                                while(lb < 64 && l < lc) {
                                    if(con[l] != '\n' && con[l] != '\r')
                                        b64line[lb++] = con[l];
                                    l++;
                                }
                                b64line[lb++] = '\n';
                                b64line[lb] = 0;
                                ld = sizeof(dec);
                                dec[0] = 0;
                                EVP_DecodeUpdate(&ectx, (unsigned char*)dec, &ld, (unsigned char*)b64line, lb);
                                lExtr += ld;
                                if(ld > 0)
                                    fwrite(dec, 1, ld, fOut);
                                lb = 0;
                            }
                        }
                        ld = 0;
                        dec[ld] = 0;
                        EVP_DecodeFinal(&ectx, (unsigned char*)dec, &ld);
                        lExtr += ld;
                        if(ld)
                            fwrite(dec, 1, ld, fOut);
                    } else if(nNc || !b64) {
                        if(lc) {
                            lExtr += lc;
                            fwrite(con, 1, lc, fOut);
                            lc = 0;

                        }
                    }
                    i = sizeof(chars);
                    //AM 24.09.08 RIK
                    eState = ST_DF_END_END;
                    break;
                }
            }
            //AM 24.09.08 RIK ST_DF_END to ST_DF_END_END_END
        } while(nRead > 0 && !err && eState < ST_DF_END_END);
    } else {
        ddocDebug(1, "ddocExtractDataFile", "Error reading file: %s", szFileName);
        SET_LAST_ERROR(ERR_FILE_READ);
    }
    if(fIn)
        fclose(fIn);
    if(fOut)
        fclose(fOut);
    if(!nNc && lSize != lExtr) {
        ddocDebug(1, "ddocExtractDataFile", "Warning! Extracted: %ld bytes but expected: %ld bytes", lExtr, lSize);
        //SET_LAST_ERROR(ERR_FILE_READ);
        //err = ERR_FILE_READ;
    }
    if(!bFound) {
        ddocDebug(1, "ddocExtractDataFile", "DF: %s not found", szDocId);
        SET_LAST_ERROR(ERR_FILE_WRITE);
        err = ERR_FILE_WRITE;
    }
    ddocDebug(3, "ddocExtractDataFile", "Extracted DF: %s to %s size: %ld expected: %ld", szDocId, szDataFileName, lExtr, lSize);
#ifdef WIN32
    free(convFileName);
    free(convDataFileName);
#endif
    return err;
}
Example #3
0
//--------------------------------------------------
// Calculates file size
// szFileName - file name
// lFileLen - pointer to a buffer where to store the file length
// returns error code or ERR_OK for success
//--------------------------------------------------
EXP_OPTION int calculateFileSize(const char* szFileName, long* lFileLen)
{
    FILE* hFile = 0;
#ifdef WIN32
    int i = 0, err = ERR_OK;
    wchar_t *convFileName = 0;
#endif

    RETURN_IF_NULL_PARAM(szFileName);
    RETURN_IF_NULL_PARAM(lFileLen);
    if(!szFileName || !strlen(szFileName)) return 0;
#ifdef WIN32
    err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i);
    ddocDebug(3, "calculateFileSize", "Opening FILE: %s, conv-file: %s len: %d", szFileName, convFileName, i);
    if((hFile = _wfopen(convFileName,L"rb")) != NULL) {
#else
    if((hFile = fopen(szFileName,"rb")) != NULL) {
#endif
        fseek(hFile, 0, SEEK_END);
        (*lFileLen) = ftell(hFile);
        ddocDebug(3, "calculateFileSize", "Closing FILE: %s, size: %ld", szFileName, (*lFileLen));
        fclose(hFile);
    } // if - fopen
    else
        SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ);
#ifdef WIN32
    if(convFileName) free(convFileName);
#endif

    return ERR_OK;
}


//--------------------------------------------------
// Calculates files SHA1-RSA signature
// szFileName - file name
// nDigestType - digest type. Supports only SHA1 (0)
// pSigBuf - buffer to store the signature
// nSigLen - buffer size, must be at least 128
//			will be updated by actual signature length
// keyfile - name of the private key file
// passwd - private key password
// returns error code or ERR_OK for success
//--------------------------------------------------
EXP_OPTION int calculateFileSignature(const char* szFileName, int nDigestType,
                                      byte* pSigBuf, int* nSigLen,
                                      const char *keyfile, const char* passwd)
{
    int err = ERR_OK;
    EVP_MD_CTX  ctx;
    byte buf[FILE_BUFSIZE];
    int i;
    FILE *f = NULL;
    EVP_PKEY* pkey = NULL;

    RETURN_IF_NULL_PARAM(szFileName);
    RETURN_IF_NULL_PARAM(pSigBuf);
    RETURN_IF_NULL_PARAM(nSigLen);
    RETURN_IF_NULL_PARAM(keyfile);
    RETURN_IF_NULL_PARAM(passwd);

    memset(pSigBuf, 0, *nSigLen);
    if(nDigestType == DIGEST_SHA1) {
        if(*nSigLen >= SIGNATURE_LEN) {
            if((err = ReadPrivateKey(&pkey, keyfile, passwd, FILE_FORMAT_PEM)) == ERR_OK) {
                if((f = fopen(szFileName,"rb")) != NULL) {
                    EVP_SignInit(&ctx, EVP_sha1());
                    for (;;) {
                        i = fread(buf, sizeof(char), FILE_BUFSIZE, f);
                        if (i <= 0) break;
                        EVP_SignUpdate (&ctx, buf, (unsigned long)i);
                    }
                    err = EVP_SignFinal(&ctx, pSigBuf, (unsigned int*)nSigLen, pkey);
                    if(err == ERR_LIB_NONE)
                        err = ERR_OK;
                    fclose(f);
                    EVP_PKEY_free(pkey);
                } // if - fopen
                else
                    err = ERR_FILE_READ;
            }
            else
                err = ERR_PRIVKEY_READ;
        }
        else
            err = ERR_SIGNATURE_LEN;
    }
    else
        err = ERR_UNSUPPORTED_DIGEST;
    if (err != ERR_OK) SET_LAST_ERROR(err);
    return err;
}
Example #4
0
//--------------------------------------------------
// Writes encrypted data to a file
// pEncData - encrypted data object [REQUIRED]
// szFileName - name of the file to write the data [REQUIRED]
// returns error code or ERR_OK
//--------------------------------------------------
EXP_OPTION int dencGenEncryptedData_writeToFile(DEncEncryptedData* pEncData, const char* szFileName)
{
  int err = ERR_OK;
  DigiDocMemBuf mbufEncData;
  FILE* hFile;
#ifdef WIN32
  wchar_t *convFileName = 0; 
  int i= 0;
  err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i);
  ddocDebug(3, "ddocGenEncryptedData_writeToFile", "file: %s, conv-file: %s len: %d", szFileName, convFileName, i);
#else
  char convFileName[1024];
  ddocConvertFileName( convFileName, sizeof(convFileName), szFileName );
#endif

  ddocDebug(3, "dencGenEncryptedData_writeToFile", "filename: %s", szFileName);
  RETURN_IF_NULL_PARAM(pEncData)
  RETURN_IF_NULL_PARAM(szFileName)
  // start of element
  mbufEncData.pMem = 0;
  mbufEncData.nLen = 0;
  err = dencGenEncryptedData_toXML(pEncData, &mbufEncData);
#ifdef WIN32
  if(!err && (hFile = _wfopen(convFileName, L"wb")) != NULL) {
#else
  if(!err && (hFile = fopen(convFileName, "wb")) != NULL) {
#endif
    fwrite(mbufEncData.pMem, mbufEncData.nLen, 1, hFile);
    fclose(hFile);
  } else {
    SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE);
    ddocDebug(1, "dencGenEncryptedData_writeToFile", "Error writing encrypted document");
  }
  // cleanup
  ddocMemBuf_free(&mbufEncData);
  return err;
}


//--------------------------------------------------
// Generates the header of XML for <EncryptedData> element
// This contains everything upto the start of base64 encoded cipher data
// pEncData - encrypted data object [REQUIRED]
// pBuf - memory buffer for storing xml [REQUIRED]
// returns error code or ERR_OK
//--------------------------------------------------
int dencGenEncryptedData_header_toXML(DEncEncryptedData* pEncData, DigiDocMemBuf* pBuf)
{
  int err = ERR_OK;
  char* p;
  int i, n;

  RETURN_IF_NULL_PARAM(pBuf)
  RETURN_IF_NULL_PARAM(pEncData)
  // xml header
  err = ddocMemAppendData(pBuf, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>", -1);
  if(err) return err;
  // start of element
  err = ddocGen_startElemBegin(pBuf, "denc:EncryptedData");
  if(err) return err;
  // xmlns:denc
  //p = dencEncryptedData_GetXmlNs(pEncData);
  //if(p)
  err = ddocGen_addAtribute(pBuf, "xmlns:denc", DENC_XMLNS_XMLENC);
  if(err) return err;
  // Id atribute
  p = (char*)dencEncryptedData_GetId(pEncData);
  if(p)
    err = ddocGen_addAtribute(pBuf, "Id", p);
  if(err) return err;
  // Type atribute
  p = (char*)dencEncryptedData_GetType(pEncData);
  if(p)
    err = ddocGen_addAtribute(pBuf, "Type", p);
  if(err) return err;
  // MimeType atribute
  p = (char*)dencEncryptedData_GetMimeType(pEncData);
  if(p)
    err = ddocGen_addAtribute(pBuf, "MimeType", p);
  if(err) return err;
  // Encoding ???
  // end of element start tag
  err = ddocGen_startElemEnd(pBuf);
  if(err) return err;
  // <EncryptionMethod>
  p = (char*)dencEncryptedData_GetEncryptionMethod(pEncData);
  if(p) {
    err = ddocGen_startElemBegin(pBuf, "denc:EncryptionMethod");
    if(err) return err;
    err = ddocGen_addAtribute(pBuf, "Algorithm", p);
    if(err) return err;
    // end of element start tag
    err = ddocGen_startElemEnd(pBuf);
    if(err) return err;
    err = ddocGen_endElem(pBuf, "denc:EncryptionMethod");
    if(err) return err;
  }
  n = dencEncryptedData_GetEncryptedKeyCount(pEncData);
  if(n > 0) {
    // <KeyInfo>
    err = ddocGen_startElemBegin(pBuf, "ds:KeyInfo");
    if(err) return err;
    // xmlns ???
    err = ddocGen_addAtribute(pBuf, "xmlns:ds", DENC_XMLNS_XMLDSIG);
    if(err) return err;
    err = ddocGen_startElemEnd(pBuf);
    if(err) return err;
    // <EncryptedKey>
    for(i = 0; i < n; i++) {
      DEncEncryptedKey* pEncKey = dencEncryptedData_GetEncryptedKey(pEncData, i);
      if(pEncKey) {
	err = dencGenEncryptedKey_toXML(pEncKey, pBuf);
	if(err) return err;
      }
    }
    // end of element <KeyInfo>
    err = ddocGen_endElem(pBuf, "ds:KeyInfo");
    if(err) return err;
  }
  // encrypted data
  err = ddocGen_startElem(pBuf, "denc:CipherData");
  if(err) return err;
  err = ddocGen_startElem(pBuf, "denc:CipherValue");
  // here would come the base64 encoded cipher data
  return err;
}