Sambaのパスワードを変更するCGIをPythonで書いてみました

# 産業で説明
- Windowsから、LinuxのSambaサーバーのパスワードを変更するには、以前はSWATというツールやwebminツールがありました。
- 現在SWATはSambaから削除されていて使用できません。
- なので、代替用のCGIをPythonでちょろっと（嘘）、書いてみました。

#こんな感じ。

```python:smbpass.cgi
#!/usr/bin/env python
#   -*- coding: utf-8   -*-

"""
Windows共有(SMB)パスワードを変更します.

注意点:
  CGIから実行する都合上、
  www-data のユーザー権限を使用して 対象サーバーに１回だけでも
  手動でssh接続する必要があります。
  (www-dataのログインシェルを有効にする必要もあります)

例：
  $ sudo bash
  # su - www-data
  $ ssh localhost

そうすると、 var/www/.ssh/known_hosts に対象サーバーが登録され、
それ以降は CGIから ssh接続が(非対話で)繋がるようになります

このプログラムの実行原理:

sshpassを使用します。
 /usr/bin/sshpass -p パスワード ssh -t ユーザー名@localhost/usr/local/bin/smbpass.sh '旧パス' '新パス'

"""

import os
import sys
import cgi
import cgitb
import subprocess
from string import Template

# CGIエラーしたときにHTMLバックトレースを有効に.
cgitb.enable()

# 環境によりエラーする
def sysCall(cmd,name,passwd,newpass):
    # 接続先サーバー.
    ssh_host = 'localhost'
    # パスワードをクォートする.
    pw    = "'" + passwd + "'"
    newpw = "'" + newpass + "'"
    log=''
    host  = name + '@' + ssh_host

    if(False):
        a = ['/usr/bin/sshpass','-p',pw,'ssh',host,'/usr/local/bin/' + cmd,pw,newpw]
        log = ' '.join(a)
        return log

    try:
        log = subprocess.check_output(['/usr/bin/sshpass','-p',passwd,'ssh','-o','StrictHostKeyChecking=no',host,'/usr/local/bin/' + cmd,pw,newpw])
        log = '<pre>' + log + '</pre>'
    except subprocess.CalledProcessError:
        log = '実行エラー : たぶん現在のパスワードが合いません'

    return log

def loadfile(file):
    """
    ファイルを読み込む
    """
    f=open(file)
    buf = f.read()
    f.close()
    return buf

def set_pw(name,oldpasswd,passwd1,passwd2):
    if(name==''):
        return 'ユーザー名が空欄です'
    if(oldpasswd==''):
        return '旧パスワードが空欄です'
    if(passwd1==''):
        return '新パスワードが空欄です'
    if(passwd2==''):
        return '新パスワードが空欄です'
    if(passwd1!=passwd2):
        return '新パスワードは同じものを２回入力してください'
    if(passwd1==oldpasswd):
        return '新パスワードが旧パスワードと同じです'

    ret = sysCall('smbpass.sh',name,oldpasswd,passwd1)
    return ret

def main():
    name=''
    result=''
    t=Template(loadfile('tmpl.txt'))
    form=cgi.FieldStorage()
    if(form.getvalue('setkey','')=='y'):
        name=form.getvalue('name','')
        oldpasswd=form.getvalue('oldpasswd','')
        passwd1=form.getvalue('passwd1','')
        passwd2=form.getvalue('passwd2','')
        result=set_pw(name,oldpasswd,passwd1,passwd2)

    # shellからデバッグしたいときはこれ.
    #result=set_pw('USERNAME','OLDPASS','NEWPASS','NEWPATH')

    # HTML表示.
    print t.substitute(name=name,result=result)

if __name__ == "__main__":
    main()

```

- 拡張子は.cgi ですが、中身はPythonです。
- きもち悪い人は smbpass.py という名前で置いて、smbpass.cgiのシンボリックリンクを貼りましょう。
- 普通にApacheからCGIとして実行します。

# テンプレートファイル
```text:tmpl.txt
Content-Type: text/html


<!DOCTYPE html>
<html><head>
<meta   charset="UTF-8">
<style type="text/css">
div.sample { font-family: monospace; }
</style>
</head>
<body>
<center>
<h1>Windows共有パスワード変更</h1>
</center>
<div class="sample">
<table>
<tr><td></td><td><b> ユーザー名と旧パスワード、新パスワードを入力してください</b></td></tr>

<form action="smbpass.cgi" method="post" name="ssh">
<tr><td>ユーザー名:</td><td>
	<input type="text" name="name" size=16 value="${name}">
</td><td>
</td></tr>

<tr><td>旧パスワード:<br>（現パスワード）</td><td>
	<input type="password" name="oldpasswd" size=32 value="">
</td><td></td></tr>

<tr><td>新パスワード:</td><td>
	<input type="password" name="passwd1" size=32 value="">
</td><td></td></tr>

<tr><td>新パスワード:<br>（同じものをもう一度）</td><td>
	<input type="password" name="passwd2" size=32 value="">
</td><td></td></tr>
<tr><td></td><td>
	<input type="hidden" name="setkey" value="y">
	<input type="submit" name="submit" value=" パスワードを変更します ">
</form>
</td></tr>
</table>
<hr>
<font color="RED" size=+2>${result}</font>
</body>
</html>
```
- HTMLで書いたSubmit用のフォームです。(smbpass.cgiと同じディレクトリに置きます）

# Sambaパスワード変更用のシェルスクリプトファイル

- これを/usr/local/bin/smbpass.sh に置いて、実行属性を付けます。

```/usr/local/bin/smbpass.sh
#!/bin/sh
OLDPW=$1
NEWPW=$2
# テストするならこちら
#echo "${OLDPW}\n${NEWPW}\n${NEWPW}\n"

echo "${OLDPW}\n${NEWPW}\n${NEWPW}\n" | /usr/bin/smbpasswd -s
```
# 動作環境（確認につかったもの）
- Ubuntu16.04LTS
- sshpass (aptで導入)
- python 2.7.12
- apache2

# 注意事項
- セキュリティ的に、かなり甘いので、信頼のおけるローカルLAN上のみに限定して使ってください。
- Sambaの設定で　「 unix password sync = yes」にしておきましょう。
- でないと、Linuxのログインパスワードが同期しないので２回目以降CGIからのsshが動きません。
- sshサーバーの設定でパスワードログインを許可する必要があります。（鍵認証のみでは動きません）

- 'ssh','-o','StrictHostKeyChecking=no' オプションを入れてあるので、www-dataユーザーから無理にlocalhostにsshを通しておく必要は無いと思います

# その他
- 皆さんSambaのパスワード管理（ユーザー側での変更）はどうされているのでしょうか。
- 以前はSWATのパスワード変更画面CGIを利用していました（遠い目）
- LDAPサーバーとかを立てたり、Windowsホストで管理しているところはSamba側での変更は必要ないのかもしれません。（よくわかっていない）
- 新規にユーザーアカウントを発行するときは管理者側が適当なシェルスクリプトを書いて乱数パスワード（初期パスワード）を発行することになると思いますが、ユーザー側でパスワード変更する手段が無いので、ちょうど困っておりました。（SWATが消滅したので）
- ユーザーがsshログインしてsmbpasswdコマンドを打ってくれれば、CGIを作る必要は無かったかもしれません（多分それは、無理です）