2021年2月9日火曜日

opensslプログラミング:受信データの待ち方/poll()の使い方

 poll() -> SSL_read() の順番で呼び出すと、データが読み込めない場合がある。

これは SSL_read() した際に socket buffer -> SSL read buffer へデータが移動しており、且つSSL_read() で全てのデータを読みきれなかった状態で、poll() に突入することになる。

相手側が既に全てのデータを送信し終り、こちらからのレスポンス待ち状態だったとすると、こちら側も poll() でデータ受信待ち状態になってしまう。

なので、SSL_read() を使う場合は、下記のよう先に受信処理を行う必要がある。

その場合、予め socket を Non-Blocking mode にしておかないと SSL_read()/recv() でブロックされるので注意。

            loop = true;

do {

               if (tls_enable == true) {

        if ((r = SSL_read(ssl, buf, sizeof buf)) <= 0) {

                       if (r == 0 || SSL_get_error(ssl, r) != SSL_ERROR_WANT_READ) {

                break;    // error

                       }

        }

              else {

                  if ((r = recv(fd, buf, sizeof buf)) <= 0) {

                      if (r == 0 || (errno != EAGAIN && errno != EWOULDBLOCK)) {

                         break;  // error

                      }

              }

              switch (poll()) {

              case -1:  perror(); loop = false; break; // error

              case 0: loop = false; break; // error

              default:  // event happened

                 break;

              }

} while (loop);


2020年12月17日木曜日

[マルチスレッド] gdbで特定のスレッドだけ動かす

set scheduler-locking on で出来る。

他のスレッドも動かす場合は set scheduler-locking off で戻す。


もっと早く知りたかったw

2020年11月6日金曜日

opensslでデフォルトの証明書を読み込む

SSL_CTX_set_default_verify_paths()を呼び出す。ただそれだけ。
いろんなサイトのサンプルで見かける  SSL_CTX_load_verify_locations() だけじゃダメだった。
SSL_CTX_load_verify_locations() は追加CA証明書を指定する用のAPI?
追加CA証明書をデフォルトのディレクトリに配置するなら、SSL_CTX_load_verify_locations()すらもいらなかった模様。
因みに  SSL_CTX_load_verify_locations() / SSL_CTX_set_default_verify_paths() どちらも呼び出さないと証明書の検証に失敗する。
このことから、openssl はデフォルトでは読み込まんのやね。
openssl verify コマンドがデフォルトの証明書を読み込まない動き。
恐らく引数の -CApath -CAfile を指定すると SSL_CTX_load_verify_locations() を呼び出すんだろうな。

関係ないけど openssl の中では X509_STORE はスタック出来るようになってるくさい。
つまり  SSL_CTX_load_verify_locations() は何度も呼ぶことが出来るのかなー?(未実験)
 
沼にハマった僕を救ってくれたのは postfix のコードでした。
postfixさん、ありがとう。 
 
でもなぁ...
curl のコード見てると、ssl_cafile, ssl_capath が指定されてない場合に、 SSL_CTX_set_default_verify_paths()を
呼び出すようになってんのよなぁ...
 https://github.com/curl/curl/blob/master/lib/vtls/openssl.c
つまり本来なら  SSL_CTX_load_verify_locations() だけでいいんとちゃうんかな...?
 
てか、openssl より nss(mozilla) とか GnuTLS とか wolfSSL の方が初心者に優しいのかなー?
 

2018年11月28日水曜日

ファイルのタイムスタンプをナノ秒まで取得

struct stat で st_mtime が struct timespec になってるからそこから取れる。
gcc -E で確認
 # 46 "/usr/include/bits/stat.h" 3 4
struct stat
  {
    __dev_t st_dev;




    __ino_t st_ino;







    __nlink_t st_nlink;
    __mode_t st_mode;

    __uid_t st_uid;
    __gid_t st_gid;

    int __pad0;

    __dev_t st_rdev;




    __off_t st_size;



    __blksize_t st_blksize;
    __blkcnt_t st_blocks;
# 91 "/usr/include/bits/stat.h" 3 4
    struct timespec st_atim;
    struct timespec st_mtim;
    struct timespec st_ctim;
# 106 "/usr/include/bits/stat.h" 3 4
    __syscall_slong_t __unused[3];
# 115 "/usr/include/bits/stat.h" 3 4
  };
 オンラインマニュアルにある st_mtime を使うと st_mtim.tv_sec に変換されてしまうので、ナノ秒をとる場合は st_mtim.tv_nsec と書かなければならない.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>

static void
usage(const char *cmd)
{
    fprintf(stderr, "Usage: %s <file...>\n", cmd);
    exit(1);
}

static void
init(int ac, char *av[])
{  
    int c;
    const char *optstr = "";

    while ((c = getopt(ac, av, optstr)) != -1) {
        switch (c) {
        case '?':
        default:
            usage(av[0]);
            break;
        }
    }
}

int
main(int ac, char *av[])
{
    int i;
    init(ac, av);
    for (i=optind; i<ac; i++) {
        struct stat stbuf;
        if (stat(av[i], &stbuf) < 0) {
            fprintf(stderr, "Stat error[%s]: %d: %s\n", av[i], errno, strerror(errno));
            continue;
        }
        char datestr[256];
        strftime(datestr, sizeof(datestr)-1, "%Y%m%d%H%I%M%S", localtime(&stbuf.st_mtime));
        fprintf(stdout, "%s ... %s.%ld\n", av[i], datestr, stbuf.st_mtim.tv_nsec);      // st_mtime ではなく st_mtim (eがない)  を指定
    }
    return 0;
}

2016年9月26日月曜日

ランダムな内容のファイルを生成するシェルスクリプト

標準出力からファイルのリストを取り出し、ランダムなテキストをランダムなサイズで出
力する

#!/bin/sh

output()
{
    linesize=`cat /dev/urandom | tr -dc '0-9' | fold -w 3 | head -n 1`
    cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n $linesize > $1
}

while read fullpath; do
    [ -d $fullpath ] && continue

    if [ -f $fullpath ]; then
        output $fullpath
        echo "Modified $fullpath"
        continue
    fi

    mkdir -p `dirname $fullpath`

    filename=`basename $fullpath`
    case $filename in
        .*)    # ドットで始まる名前はディレクトリにする
            mkdir -p $fullpath
            ;;
        *)
            output $fullpath
            ;;
    esac
    echo "Created $fullpath"
done

exit 0

2016年3月22日火曜日

sh でファイルから1行ずつ読み込む

http://d.hatena.ne.jp/higher_tomorrow/20110504/1304472902 参照
  • ファイルをRead Open
    exec [fd]< ファイル
  • ファイルから読み込む
    read line 0<&[fd]
  • ファイルを閉じる
    exec [fd]<&-


2014年9月18日木曜日

Doxygen & Graphviz でリバースエンジニアリング


環境: RHEL6.x

インストールパッケージ
  • RHELインストールディスクから
    • doxygen-1.6.1-6.el6.x86_64
  • RHEL EPELリポジトリから(rpm検索サイトから検索できた)
    • ann-libs-1.1.1-4.el6.x86_64.rpm
    • gts-0.7.6-19.20111025.el6.x86_64.rpm
  • Graphviz本家から
    • graphviz-plugins-gd-2.38.0-1.el6.x86_64
    • graphviz-plugins-core-2.38.0-1.el6.x86_64
    • graphviz-gd-2.38.0-1.el6.x86_64
    • graphviz-2.38.0-1.el6.x86_64
    • graphviz-libs-2.38.0-1.el6.x86_64
    • graphviz-doc-2.38.0-1.el6.noarch

作業メモ

設定ファイルのデフォルトの作成
% doxygen -g Doxygen/Config

設定ファイルの編集
% vi Doxygen/Config
PROJECT_NAME = hoge                     (お好みの名前)
OUTPUT_DIRECTORY = Doxygen
OUTPUT_LANGUAGE = Japanese-en
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES                   (お好みで)
EXTRACT_STATIC = YES                     (お好みで)
EXTRACT_LOCAL_METHODS = YES    (お好みで)
EXTRACT_ANON_NSPACES = YES      (お好みで)
INPUT =  . ../lib/http ../../common ../../modules (.はいらないかな?)
RECURSIVE = YES
INCLUDE_PATH = include ../../lib         (RECURSIVEがYESだから include はいらないかな?)
HAVE_DOT = YES
UML_LOOK = YES
CALL_GRAPH = YES                            (呼び出し先の網羅)
CALLER_GRAPH = YES                        (呼び出し元の網羅)
INPUT_FILTER = nkf とか?                 (まだ使ってない)
実行
% doxygen Doxygen/Config

作成された html(Doxygen/html/index.html) をブラウザでチェック

参考

http://okwave.jp/qa/q3709415.html
Doxygenを使おう
DoxywizardにおけるExpert設定方法