Saturday, December 22, 2007

ldap connect AD

開始:
1. 建立 IIS SSL
2. 將 CA Certificate 加入至 jre keystore 裡
3. JNDI 連 AD

1. 建立 IIS SSL:
Install Windows 2003 Server:

Install AD:
Start -> Run -> dcpromote
domain name : joeyta-DOT-local
NT domain name : joeytaserver
即 Fully Qualified Domain Name (FQDN) 為 joeytaserver.joeyta-DOT-local

先安裝 IIS , 再安裝 CA.

Install IIS:
Start -> Programs -> Administrative Tools -> Configure Your Server Wizard
->> Next -> Next -> Application server (IIS, ASP.NET) -> Next

進入 http://joeyserver.joeyta.local/postinfo.html 表示安裝成功.

Install CA:
Start -> Settings -> Control Panel -> Add or Remove Programs
->> Add/Remove Windows Components
選擇 Certificate Services -> Next
選擇 Enterprise root CA -> Next
Common name for this CA: testca -> Next

進入 http://joeyserver.joeyta.local/CertSrv 表示安裝成功.


Generating a Certificate Signing Request:
Start -> Programs -> Administrative Tools -> Internet Information Services (IIS) Manager
->> Internet Information Services -> (local computer) -> Web Sites
-> > 右鍵點選 Default Web Site -> Properties
選擇 "Directory Security" -> Server Certificate
->> Create a new certificate -> Prepare the request now, but send it later
一直按 Next , 需要注意的是 Common name 必須為 joeyserver.joeyta.local, 這是給使用者連 ssl 的 website.
最後產生 certificate request file , 預設為 c:\certreq.txt


Request a certificate on CA:
進入 http://joeyserver.joeyta.local/CertSrv
按 Request a certificate -> advanced certificate request
-> Submit a certificate request by using a base-64-encoded CMC or PKCS#10 file, or submit a renewal request by using a base-64-encoded PKCS#7 file
使用 notepad 打開 c:\certreq.txt , copy c:\certreq.txt 內容貼至 Saved Request:
Certificate Template 選擇 Web Server, 按 Submit
然後點選 Download certificate , 將 certnew.cer 儲存至 c:\certnew.cer


Installing a Certificate:
Start -> Programs -> Administrative Tools -> Internet Information Services (IIS) Manager
->> Internet Information Services -> (local computer) -> Web Sites
-> > 右鍵點選 Default Web Site -> Properties
選擇 "Directory Security" -> Server Certificate
->> Process the pending request and install the certificate -> Next
Path and file name: c:\certnew.cer -> Next
SSL port this web site should use: 443 -> Next -> Next -> Finish


2. 將 CA Certificate 加入至 jre keystore 裡:
進入 http://joeyserver.joeyta.local/CertSrv
點選 Download a CA certificate, certificate chain, or CRL
點選 Download CA certificate , 然後下載並改名為 c:\testca_cert.cer

然後執行 command:
c:\temp>keytool -import -alias testca_cert -file "/testca_cert.cer" -keystore "/jdk1.5.0_09/jre/lib/security/cacerts" -storepass "changeit"

出現 Trusted this certificate? 按 "y" 即新增成功.


3. JNDI 連 AD:

/***************************** LDAPFastBind.java *****************/
package test.ldap;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Hashtable;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.StartTlsRequest;
import javax.naming.ldap.StartTlsResponse;

class FastBindConnectionControl implements Control {
public byte[] getEncodedValue() {
return null;
}

public String getID() {
return "1.2.840.113556.1.4.1781";
}

public boolean isCritical() {
return true;
}
}

public class LDAPFastBind {
public Hashtable env = null;

public LdapContext ctx = null;

public Control[] connCtls = null;

public LDAPFastBind(String ldapurl) {
env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.PROVIDER_URL, ldapurl);

env.put(Context.SECURITY_PROTOCOL,"ssl");

String keystore = "/jdk1.5.0_09/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore",keystore);

connCtls = new Control[] { new FastBindConnectionControl() };

// first time we initialize the context, no credentials are supplied
// therefore it is an anonymous bind.

try {
ctx = new InitialLdapContext(env, connCtls);

} catch (NamingException e) {
System.out.println("Naming exception " + e);
}
}

public boolean Authenticate(String username, String password) {
try {
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, username);
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
ctx.reconnect(connCtls);
System.out.println(username + " is authenticated");
return true;
}

catch (AuthenticationException e) {
System.out.println(username + " is not authenticated");
System.out.println(e);
return false;
} catch (NamingException e) {
System.out.println(username + " is not authenticated");
System.out.println(e);
return false;
}
}

public void finito() {
try {
ctx.close();
System.out.println("Context is closed");
} catch (NamingException e) {
System.out.println("Context close failure " + e);
}
}

public void printUserAccountControl() {
try {

// Create the search controls
SearchControls searchCtls = new SearchControls();

// Specify the search scope
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

// specify the LDAP search filter
//String searchFilter = "(&(objectClass=user)(CN=test))";
//String searchFilter = "(&(objectClass=group))";
String searchFilter = "(&(objectClass=user)(CN=peter lee))";

// Specify the Base for the search
String searchBase = "DC=joeyta,DC=local";

// initialize counter to total the group members
int totalResults = 0;

// Specify the attributes to return
String returnedAtts[] = { "givenName", "mail" };
searchCtls.setReturningAttributes(returnedAtts);

// Search for objects using the filter
NamingEnumeration answer = ctx.search(searchBase, searchFilter,
searchCtls);

// Loop through the search results
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();

System.out.println(">>>" + sr.getName());

// Print out the groups

Attributes attrs = sr.getAttributes();
if (attrs != null) {

try {
for (NamingEnumeration ae = attrs.getAll(); ae
.hasMore();) {
Attribute attr = (Attribute) ae.next();
System.out.println("Attribute: " + attr.getID());
for (NamingEnumeration e = attr.getAll(); e
.hasMore(); totalResults++) {

System.out.println(" " + totalResults + ". "
+ e.next());
}

}

} catch (NamingException e) {
System.err.println("Problem listing membership: " + e);
}

}
}

System.out.println("Total attrs: " + totalResults);

}

catch (NamingException e) {
System.err.println("Problem searching directory: " + e);
}

}

public boolean adminChangePassword(String sUserName, String sNewPassword){
try {

//set password is a ldap modfy operation
ModificationItem[] mods = new ModificationItem[1];

//Replace the "unicdodePwd" attribute with a new value
//Password must be both Unicode and a quoted string
String newQuotedPassword = "\"" + sNewPassword + "\"";
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");

mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword));

// Perform the update
ctx.modifyAttributes(sUserName, mods);

System.out.println("Reset Password for: " + sUserName);

return true;
}
catch (NamingException e) {
System.out.println("Problem resetting password: " + e);
}
catch (UnsupportedEncodingException e) {
System.out.println("Problem encoding password: " + e);
}
return false;
}

public boolean userChangePassword(String sUserName, String sOldPassword, String sNewPassword){
try {
//StartTlsResponse tls = (StartTlsResponse)ctx.extendedOperation(new StartTlsRequest());
//tls.negotiate();

//change password is a single ldap modify operation
//that deletes the old password and adds the new password
ModificationItem[] mods = new ModificationItem[2];

//Firstly delete the "unicdodePwd" attribute, using the old password
//Then add the new password,Passwords must be both Unicode and a quoted string
String oldQuotedPassword = "\"" + sOldPassword + "\"";
byte[] oldUnicodePassword = oldQuotedPassword.getBytes("UTF-16LE");
String newQuotedPassword = "\"" + sNewPassword + "\"";
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");

mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("unicodePwd", oldUnicodePassword));
mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword));

// Perform the update
ctx.modifyAttributes(sUserName, mods);

System.out.println("Changed Password for: " + sUserName);
//tls.close();
return true;

}
catch (NamingException e) {
System.err.println("Problem changing password: " + e);
}
catch (UnsupportedEncodingException e) {
System.err.println("Problem encoding password: " + e);
} catch ( Exception e){
System.err.println("Problem: " + e);
}
return false;
}

public boolean createNewUser(String sGroupName, String sUserName){
try {
// Create attributes to be associated with the new user
Attributes attrs = new BasicAttributes(true);

//These are the mandatory attributes for a user object
//Note that Win2K3 will automagically create a random
//samAccountName if it is not present. (Win2K does not)
attrs.put("objectClass","user");
attrs.put("sAMAccountName","AlanT");
attrs.put("cn","Alan Tang");

//These are some optional (but useful) attributes
attrs.put("givenName","Alan");
attrs.put("sn","Tang");
attrs.put("displayName","Alan Tang");
attrs.put("description","Engineer");
attrs.put("userPrincipalName","alan-AT-joeyta.local");
attrs.put("mail","alang-AT-mail.joeyta-DOT-local");
attrs.put("telephoneNumber","123 456 789");

//some useful constants from lmaccess.h
int UF_ACCOUNTDISABLE = 0x0002;
int UF_PASSWD_NOTREQD = 0x0020;
int UF_PASSWD_CANT_CHANGE = 0x0040;
int UF_NORMAL_ACCOUNT = 0x0200;
int UF_DONT_EXPIRE_PASSWD = 0x10000;
int UF_PASSWORD_EXPIRED = 0x800000;

//Note that you need to create the user object before you can
//set the password. Therefore as the user is created with no
//password, user AccountControl must be set to the following
//otherwise the Win2K3 password filter will return error 53
//unwilling to perform.

attrs.put("userAccountControl",Integer.toString(UF_NORMAL_ACCOUNT + UF_PASSWD_NOTREQD + UF_PASSWORD_EXPIRED+ UF_ACCOUNTDISABLE));

// Create the context
Context result = ctx.createSubcontext(sUserName, attrs);
System.out.println("Created disabled account for: " + sUserName);

//now that we've created the user object, we can set the
//password and change the userAccountControl
//and because password can only be set using SSL/TLS
//lets use StartTLS

//StartTlsResponse tls = (StartTlsResponse)ctx.extendedOperation(new StartTlsRequest());
//tls.negotiate();

//set password is a ldap modfy operation
//and we'll update the userAccountControl
//enabling the acount and force the user to update ther password
//the first time they login
ModificationItem[] mods = new ModificationItem[2];

//Replace the "unicdodePwd" attribute with a new value
//Password must be both Unicode and a quoted string
String newQuotedPassword = "\"P-AT-ssw0rd\"";
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");

mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword));
mods[1] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("userAccountControl",Integer.toString(UF_NORMAL_ACCOUNT + UF_PASSWORD_EXPIRED)));

// Perform the update
ctx.modifyAttributes(sUserName, mods);
System.out.println("Set password & updated userccountControl");


//now add the user to a group.

try {
ModificationItem member[] = new ModificationItem[1];
member[0]= new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("member", sUserName));

ctx.modifyAttributes(sGroupName,member);
System.out.println("Added user to group: " + sGroupName);

}
catch (NamingException e) {
System.err.println("Problem adding user to group: " + e);
}
//Could have put tls.close() prior to the group modification
//but it seems to screw up the connection or context ?
//tls.close();

System.out.println("Successfully created User: " + sUserName);
return true;

}
catch (NamingException e) {
System.err.println("Problem creating object: " + e);
}

catch (IOException e) {
System.err.println("Problem creating object: " + e);
}
return false;
}

public boolean addUserToGroup(LdapContext ctx, String userDN, String groupDN) {
try{
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("member", userDN));
ctx.modifyAttributes(groupDN, mods);
System.out.println("Added user " + userDN + " to group " + groupDN);
return true;
} catch (NamingException ne){
System.err.println("Problem add user to group: " + ne);
}
return false;
}

public boolean removeUserFromGroup(LdapContext ctx, String userDN, String groupDN) {
try{
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("member", userDN));
ctx.modifyAttributes(groupDN, mods);
System.out.println("Remove user " + userDN + " from group " + groupDN);
return true;
} catch (NamingException ne){
System.err.println("Problem remove user from group: " + ne);
}
return false;
}

}
/***************************** LDAPFastBind.java *****************/





/***************************** LDAPClient.java *****************/
package test.ldap;

class LDAPClient {
public static void main(String[] args) {
// Could also use ldaps over port 636 to protect the communication to
// the
// Active Directory domain controller. Would also need to add
// env.put(Context.SECURITY_PROTOCOL,"ssl") to the "server" code
//String ldapurl = "ldap://joeyserver.joeyta.local:389";
String ldapurl = "ldap://joeyserver.joeyta.local:636";

LDAPFastBind ctx = new LDAPFastBind(ldapurl);

String sAdminUserName = "CN=Administrator,CN=Users,DC=joeyta,DC=local";
String sAdminPassword = "I@mRoot";

// String sUserName = "CN=peter lee,CN=Users,DC=joeyta,DC=local";
String sUserName = "joeyta\\peter";
// String sUserName = "peter@joeyta.local";

String sOldPassword = "P@ssw0rd";
String sNewPassword = "P@$w0rd";

String sNewUserName = "CN=Alan Tang,CN=Users,DC=joyeta,DC=local";
String sNewGroupName = "CN=test,CN=Users,DC=joeyta,DC=local";

boolean IsAuthenticated = ctx.Authenticate(sAdminUserName, sAdminPassword);
// boolean IsAuthenticated = ctx.Authenticate(sUserName, sOldPassword);

ctx.printUserAccountControl();

ctx.createNewUser(sNewGroupName, sNewUserName);

//boolean IsAdminSuccessChangePWD = ctx.adminChangePassword(sUserName,sNewPassword);
//boolean IsUserSuccessChangePWD = ctx.userChangePassword(sUserName,sOldPassword,sNewPassword);

ctx.finito();

}
}
/***************************** LDAPClient.java *****************/

Saturday, December 15, 2007

Ubuntu 好用軟體

edonkey - aMule

sudo apt-get install aMule

不用說了吧,反正就是那回事,中文,日文都 ok 的啦

IM - Gaim(Pidgin)

萬用 Instant Messager,Ubuntu內建,新版改名叫 Pidgin,變得漂亮多了

BBS - PCManX

sudo apt-get install pcmanx-gtk2

好用的 BBS client,記得要換字型比較好看

Packet Sniffer - Ethereal

sudo apt-get install ethereal

看封包內容的軟體,功能強大,不過我只拿來 debug http 的 resquest/response

BT - Deluge

sudo apt-get install deluge-torrent

就是 BT,gnome 是有內建,但是那個太陽春了,換這個 python 寫的吧

看漫畫 - Comix

sudo apt-get install comix

這個超讚,用電腦看漫畫必備!可以設定左右兩頁合併成一頁,也支援右頁翻到左頁 (漫畫都是右到左)。當然你要拿來瀏覽一般圖片也行,速度很快。

向量繪圖 - Inkscape

sudo apt-get install inkscape

雖然我不會美工,但有時候還是得改一些 icon,或是做一些簡單的 logo。inkscape 用起來挺直覺的,連我這個繪圖白吃都玩的起~

安裝外部軟體 - Automatix

sudo apt-get install automatix2

Skype, Adobe Reader, Windows codec, 讀寫 NTFS 等等涉及版權的軟體安裝起來都超麻煩的,這時 Automatix 就派上用場了,點幾下那些難纏的軟體通通裝好設定完全。爽~

錄音 - Audacity

sudo apt-get install audacity

多軌錄音軟體,介面很醜... 不過夠我錄音樂用了。

看影片 - vlc

sudo apt-get install vlc

你什麼 codec 都可以不裝,就是不能漏掉這個 vlc,連 wmv9 都可以看,真是天賜啊

字典 - 星際譯王

sudo apt-get install stardict

沒有這個字典活不下去

virtual machine - VirtualBox

sudo apt-get install virtualbox

我已經放棄 vmware 了,vmware player 太陽春,vmware workstation 要錢,vmware server 安裝太麻煩。每次 kernel 升級 vmware 就要重新 compile... etc 真是煩死了。一氣之下轉換到 virtualbox,從此過著幸福快樂的日子。還死守在 vmware 的同胞們快點換吧~

screen action - brightside

sudo apt-get install brightside

裝了這個就可以設定滑鼠碰觸畫面角落,開啟特定程式或是顯示桌面,我用慣 mac 的滑鼠顯示桌面了,所以裝這個來模擬。

Palm - J-Pilot

sudo apt-get install jpilot

如果你跟我一樣還在用那個不上道的 palm (treo650),這個可以解決 sync 的問題,Big5 中文也通喔!(如果弄得到 iphone 我就把 treo 給丟了)

nVidia - envy

sudo apt-get install envy

nVidia 的用戶,一定得安裝 envy。這個軟體可以解決所有有關 nVidia 的問題,XWindow 裝不起來嗎?beryl 特效弄不出來嗎?想裝 nVidia 官方的 driver 嗎?裝 envy 就對了。我的 LCD 是 LED 背光,因此顏色是偏藍的,這時就得靠 nVidia 官方的 nvidia-setting 這個工具來微調了。用 envy 安裝官方 driver 後,輕輕鬆鬆搞定!

Google Desktop

http://desktop.google.com/linux

google 最新推出的 linux 版桌面搜尋,安裝後 ctrl 兩下就能搜尋囉,還蠻好用地,算是補足 linux 一直欠缺的功能。啥?你說之前已經有 beagle 了?拜託,那是用 mono 寫得耶,好不容易轉到 linux 了,幹嘛還被 ms 套牢?

中文字型 OpenDesktop Font

http://www.opendesktop.org.tw/modules/news/article.php?storyid=106

經由 OpenDesktop 團隊的努力,我們有全世界最漂亮、最清楚的中文字型囉。Mac上字型透過獨家的 render 技術產生的字型很棒,但就算 render 技術再強,永遠也比不上一個個精雕細啄的點陣字啊!

其他太基本的 gcin, java, eclipse, gimp, remote desktop 等等就不提了

Thursday, October 25, 2007

vpn client in ubuntu

1. 安裝 Network Manager

在 gnome 環境下,有一個套件叫作 Network Manager。它有幾個好處:

* 可以像 windows 一樣自動尋找,並管理無線網路
* 可以在有線及無線網路中互相切換
* 可以利用 plugin 來連結 vpn :D

用了這個軟體後,在 nb 上使用無線網路就變得簡單又方便了。所以首先我們要安裝 Network Manager

sudo apt-get install network-manager
sudo apt-get install network-manager-gnome

Network Manager 是一個系統的 service,而 Network Manager Gnome 則提供了一個 gnome 的 applet 來顯示網路狀態。所以我們要讓 gnome 在啟動時,自動執行這個 applet。

在 系統>偏好設定>作業階段>初始啟動程式 下
新增一個初始啟動指令 nm-applet
這樣下次重新啟動 xorg 或重啟電腦後,在右上角的程式狀態通知區就會看到一個網路連線的圖示了。(目前先不要重啟哦)

不過如果要讓 Network Manager 管理網路連線,就不能讓 gnome 內建的網路管理工具管理。所以我們要先取消它的管理權。

在 系統>管理>網路 下
針對你想讓 Network Manager 管理的介面,設定屬性
啟用這個連線上不要打勾!

2. 安裝及設定 VPN

接著要安裝 pptp vpn 相關的軟體,由於 Network Manager 的 pptp Plugin 目前還是 universe的,所以要先打開 universe 的套件庫。然後執行以下指令

sudo apt-get install pptp-linux
sudo apt-get install network-manager-pptp


接下來,就可以重啟 xorg 或電腦了。
重啟後,在右上角看到網路連線的圖示,按左鍵就可以設定網路或 vpn.
a. 選擇 VPN Connections > Configure VPN


b. 選擇 PPTP Tunnel

c. 設定 vpn gateway

d. 在 Authentication 下面我是這樣設的。

e. Encryption 下我是都沒有勾

存檔後就可以了,接著就來連線。
點選 vpn 的選項之後,右上角的圖示就會轉來轉去,轉完後就可以連上了。

3. Troubleshooting

我第一次裝的時候,vpn connection 設定,我所設定的 vpn 就是不會出來。網路上有 FAQ 說要刪除一些設定檔: (原文)

/etc/NetworkManager/VPN/nm-pptp-service.name
/etc/dbus-1/system.d/nm-pptp-service.conf

我當時不加思索照作,當場更慘,一旦想要增加新的 vpn,馬上就會出現沒有安裝 vpn 相關軟體的對話窗。我當場利用 windows 思維,重裝 network-manager-pptp,不過並沒有效。
後來是把 network-manager, linux-pptp, network-manager-pptp 及 network-manager-gnome 全部都進行徹底移除 (用 synaptic 即可)。確定 /etc/NetworkManager 及 ~/.gconf/system/networking/vpn_connections 不存在或裏面沒檔案了,再一個個重新裝回來。重裝之後就正常了。

根據我現在正常的狀態,上述兩個檔案的確是不存在,所以該 FAQ 的作法似乎也有其道理。不過確切的原因還有待研究。

Wednesday, October 17, 2007

用 linux 連接 windows 的share folder

mount -t smbfs -o iocharset=utf8,codepage=unicode,unicode,username='<domain>\doug' //192.168.128.221/TDD /mnt/tdd/

Friday, August 10, 2007

java display 中文 in linux

1.
首先在java目錄下的jre/lib/fonts下建立fallback目錄
例如
$sudo mkdir /usr/lib/jdk1.5.0_05/jre/lib/fonts/fallback
2.
然後在fallback目錄下放置中文字體的檔案或連結
$sudo ln -s /usr/share/fonts/truetype/arphic/uming.ttf
/usr/lib/jdk1.5.0_05/jre/lib/fonts/fallback/
3.
進入fallback目錄中建立fonts.scale檔案
$cd /usr/lib/jdk1.5.0_05/jre/lib/fonts/fallback/
$sudo mkfontscale
4
最後將fonts/fallback/fonts.scale檔的內容貼到fonts/fonts.dir
兩個檔案的第一行數字加總到fonts.dir內

測試的話可以ControlCenter試試,若叫出來是中文的那麼應該就可以了

$/usr/lib/jdk1.5.0_05/bin/ControlPane

Sunday, May 13, 2007

抗工作壓力

時間久了,往往對寫程式的熱情會遞減
原本在 10 分鐘可以完成的,會因為下不了手而延遲,導致時間到了
卻沒有任何進展

如何解決此問題呢,自己也在慢慢的摸索當中

跳脫此框框可以讓自己再往上成長一步,也讓生活可以更快活
不是嗎?